diff --git a/.gitignore b/.gitignore index 23f2926b..9b8dcfda 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ Package.resolved Package.pins /*.xcodeproj /build +/.swiftpm diff --git a/.travis.yml b/.travis.yml index 90cc9a9b..33592517 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,40 +5,43 @@ matrix: include: - os: osx language: objective-c - osx_image: xcode9 + osx_image: xcode12.2 before_install: - export PATH=/usr/local/opt/llvm/bin:"${PATH}" - brew update - - brew install llvm + - brew install llvm@11 + - echo 'export PATH="/usr/local/opt/llvm@11/bin:$PATH"' >> /Users/travis/.bash_profile + - source /Users/travis/.bash_profile - sudo swift utils/make-pkgconfig.swift script: - - swift test + - swift test -Xlinker -w - os: linux language: generic sudo: required - dist: trusty + dist: focal env: - - LLVM_API_VERSION=5.0 + - LLVM_API_VERSION=11 before_install: - export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:"${PKG_CONFIG_PATH}" - wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - - sudo apt-add-repository "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-${LLVM_API_VERSION} - main" + - sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${LLVM_API_VERSION} main" + - sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - sudo apt-get update - - sudo apt-get install llvm-${LLVM_API_VERSION} libc++1 + - sudo apt-get install -y binutils git gnupg2 libc6-dev libcurl4 libedit2 libgcc-9-dev libpython2.7 libsqlite3-0 libstdc++-9-dev libxml2 libz3-dev pkg-config tzdata zlib1g-dev + - sudo apt-get install -y llvm-${LLVM_API_VERSION} llvm-${LLVM_API_VERSION}-dev libc++1 libtinfo5 libncurses5 - sudo cp /usr/lib/x86_64-linux-gnu/libc++.so.1.0 /usr/lib/ - sudo ln -sf /usr/lib/libc++.so.1.0 /usr/lib/libc++.so - sudo rm -rf /usr/local/clang-*/bin/llvm-config - - ls -l /usr/bin/llvm-config* - sudo rm -f /usr/bin/llvm-config - sudo ln -s /usr/bin/llvm-config-${LLVM_API_VERSION} /usr/bin/llvm-config + - ls /usr/lib/llvm-11/include/llvm-c - wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import - - - wget https://swift.org/builds/swift-4.0-release/ubuntu1404/swift-4.0-RELEASE/swift-4.0-RELEASE-ubuntu14.04.tar.gz - - tar xzf swift-4.0-RELEASE-ubuntu14.04.tar.gz - - export PATH=${PWD}/swift-4.0-RELEASE-ubuntu14.04/usr/bin:"${PATH}" - - sudo ./swift-4.0-RELEASE-ubuntu14.04/usr/bin/swift utils/make-pkgconfig.swift + - wget https://swift.org/builds/swift-5.2.5-release/ubuntu1804/swift-5.2.5-RELEASE/swift-5.2.5-RELEASE-ubuntu18.04.tar.gz + - tar xzf swift-5.2.5-RELEASE-ubuntu18.04.tar.gz + - export PATH=${PWD}/swift-5.2.5-RELEASE-ubuntu18.04/usr/bin:"${PATH}" + - sudo ./swift-5.2.5-RELEASE-ubuntu18.04/usr/bin/swift utils/make-pkgconfig.swift script: - - swift test + - sudo ./swift-5.2.5-RELEASE-ubuntu18.04/usr/bin/swift test notifications: slack: secure: ek/+U+e44bqP8+QCHojy2LhrN9iwY3N/TNNqNG5FZrp09Vidrd5KXWJOXFxlGrpeWdgTpi089YbEdTfxpcDIudUqDqLwPzS7wePiG2cEC1OT6l3yrhI4AvOe7EsNSOX8gzkuEnmrZVHwLLGe7JeR7JIQKoHMZsBcPYDnO8kRP0Ei3zOh47YUn75SE87egAgZOVBDbZYO3GWRa4WX64s8gaQYQ9a7EoUY0oX9rQ48FJs3rmEIhvIXdcOj9bGX7+o0j7l+IFial/Qh+B6bp4XkZU/tUVP6cuNVI1vxE1weVGCBhgt5wLhXTMewzoE5D1IgMZHVuzIBcDbBthSzQRttLSlYar6xTjXtRtOnb8tqZMWfUj3HBYCFYqtz7PGnZ3IflEVsPJW6tgSsoeB6egjzb8APP9mvhm8+zb1jQG1dqXLWErMjWqhlyPVPmHrxU2w/OLWLAJPY94GVmLnSuOw2pSz41spuEY80JcVVzoRbAOQWrwAujq2S3k93yvKpGq4eaT72Mt8g1CyZesByvzcLk99LEJSpqOIxUqXBd4RwHhay/sq8LllyyqY8ORsxEgwQluOAjEhATO/t/HUsu2ndn1k38U1c4HqXW7FDs1hffYEzZ/PGxciCS6Vt1bfST+iq34pzqpanENQCnX6mSR+D+M7mHlCWdsUihmxEcs5knuM= diff --git a/Package.swift b/Package.swift index 63520751..e4e3d4e4 100644 --- a/Package.swift +++ b/Package.swift @@ -1,23 +1,36 @@ -// swift-tools-version:4.0 +// swift-tools-version:5.2 import PackageDescription let package = Package( name: "LLVM", + platforms: [ + .macOS(.v10_14), + ], products: [ .library( name: "LLVM", targets: ["LLVM"]), ], dependencies: [ - .package(url: "https://github.com/llvm-swift/cllvm.git", from: "0.0.3"), .package(url: "https://github.com/llvm-swift/FileCheck.git", from: "0.0.3"), ], targets: [ + .systemLibrary( + name: "cllvm", + pkgConfig: "cllvm", + providers: [ + .brew(["llvm"]), + ]), + .target( + name: "llvmshims", + dependencies: ["cllvm"]), .target( - name: "LLVM"), + name: "LLVM", + dependencies: ["cllvm", "llvmshims"]), .testTarget( name: "LLVMTests", dependencies: ["LLVM", "FileCheck"]), - ] + ], + cxxLanguageStandard: .cxx14 ) diff --git a/README.md b/README.md index fbe8f409..9ea9f6be 100644 --- a/README.md +++ b/README.md @@ -13,18 +13,15 @@ The root unit of organization of an LLVM IR program is a `Module` let module = Module(name: "main") ``` -LLVM IR is construction is done with an `IRBuilder` object. An `IRBuilder` is a cursor pointed inside a context, and as such has ways of extending that context and moving around inside of it. +LLVM IR construction is handled by `IRBuilder` objects. An `IRBuilder` is a cursor pointed inside a context, and as such has ways of extending that context and moving around inside of it. -Defining a simple function and moving the cursor to a point where we can begin inserting instructions is done like so: +Defining a function and moving the cursor to a point where we can begin inserting instructions is done like so: ```swift let builder = IRBuilder(module: module) -let main = builder.addFunction( - name: "main", - type: FunctionType(argTypes: [], - returnType: VoidType()) - ) +let main = builder.addFunction("main", + type: FunctionType([], IntType.int64)) let entry = main.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entry) ``` @@ -42,7 +39,7 @@ This simple program generates the following IR: ```llvm // module.dump() -define void @main() { +define i64 @main() { entry: ret i64 42 } @@ -95,11 +92,9 @@ func calculateFibs(_ backward : Bool) -> Double { Notice that the value of `retVal` depends on the path the flow of control takes through this program, so we must emit a PHI node to properly initialize it: ```swift -let function = builder.addFunction( - "calculateFibs", - type: FunctionType(argTypes: [IntType.int1], - returnType: FloatType.double) - ) +let function = builder.addFunction("calculateFibs", + type: FunctionType([IntType.int1], + FloatType.double)) let entryBB = function.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entryBB) @@ -107,7 +102,7 @@ builder.positionAtEnd(of: entryBB) let local = builder.buildAlloca(type: FloatType.double, name: "local") // Compare to the condition -let test = builder.buildICmp(function.parameters[0], IntType.int1.zero(), .notEqual) +let test = builder.buildICmp(function.parameters[0], IntType.int1.zero(), .equal) // Create basic blocks for "then", "else", and "merge" let thenBB = function.appendBasicBlock(named: "then") @@ -138,7 +133,7 @@ phi.addIncoming([ (elseVal, elseBB), ]) builder.buildStore(phi, to: local) -let ret = builder.buildLoad(local, name: "ret") +let ret = builder.buildLoad(local, type: FloatType.double, name: "ret") builder.buildRet(ret) ``` @@ -171,11 +166,14 @@ LLVMSwift provides a JIT abstraction to make executing code in LLVM modules quic ```swift // Setup the JIT -let jit = try! JIT(module: module, machine: TargetMachine()) +let jit = try JIT(machine: TargetMachine()) typealias FnPtr = @convention(c) (Bool) -> Double +_ = try jit.addEagerlyCompiledIR(module) { (name) -> JIT.TargetAddress in + return JIT.TargetAddress() +} // Retrieve a handle to the function we're going to invoke -let fnAddr = jit.addressOfFunction(name: "calculateFibs") -let fn = unsafeBitCast(fnAddr, to: FnPtr.self) +let addr = try jit.address(of: "calculateFibs") +let fn = unsafeBitCast(addr, to: FnPtr.self) // Call the function! print(fn(true)) // 0.00917431192660551... print(fn(false)) // 0.0112359550561798... @@ -183,11 +181,11 @@ print(fn(false)) // 0.0112359550561798... ## Installation -There are a couple, annoying steps you need to get it working before it'll -build. +There are a couple annoying steps you need to accomplish before building +LLVMSwift: -- Install LLVM 4.0 using your favorite package manager. For example: - - `brew install llvm` +- Install LLVM 11.0+ using your favorite package manager. For example: + - `brew install llvm@11` - Ensure `llvm-config` is in your `PATH` - That will reside in the `/bin` folder wherever your package manager installed LLVM. @@ -197,6 +195,12 @@ build. Once you do that, you can add LLVMSwift as a dependency for your own Swift compiler projects! +### Installation with Swift Package Manager + +```swift +.package(url: "https://github.com/llvm-swift/LLVMSwift.git", from: "0.8.0") +``` + ### Installation without Swift Package Manager We really recommend using SwiftPM with LLVMSwift, but if your project is @@ -223,3 +227,4 @@ all its code generation. This project is released under the MIT license, a copy of which is available in this repo. + diff --git a/Sources/LLVM/AddressSpace.swift b/Sources/LLVM/AddressSpace.swift new file mode 100644 index 00000000..b0d36ee7 --- /dev/null +++ b/Sources/LLVM/AddressSpace.swift @@ -0,0 +1,66 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +/// An address space is an identifier for a target-specific range of address values. An address space is a +/// fundamental part of the type of a pointer value and the type of operations that manipulate memory. +/// +/// LLVM affords a default address space (numbered zero) and places a number of assumptions on pointer +/// values within that address space: +/// - The pointer must have a fixed integral value +/// - The null pointer has a bit-value of 0 +/// +/// These assumptions are not guaranteed to hold in any other address space. In particular, a target may +/// allow pointers in non-default address spaces to have *non-integral* types. Non-integral pointer types +/// represent pointers that have an unspecified bitwise representation; that is, the integral representation may +/// be target dependent or have an unstable value. Further, outside of the default address space, it is not +/// always the case that the `null` pointer value, especially as returned by +/// `IRType.constPointerNull()` has a bit value of 0. e.g. A non-default address space may use +/// an offset-based or segment-based addressing mode in which 0 is a valid, addressable pointer value. +/// +/// Target-Level Address Space Overrides +/// ==================================== +/// +/// A target may choose to override the default address space for code, data, and local allocations through the +/// data layout string. This has multiple uses. For example, the address space of an `alloca` is *only* +/// configurable via the data layout string, because it is a target-dependent property. There are also +/// use-cases for overriding language standards e.g. the C standard requires the address-of operator applied +/// to values on the stack to result in a pointer in the default address space. However, many OpenCL-based +/// targets consider the stack to be a private region, and place such pointers in a non-default address space. +/// +/// Care must be taken when interacting with these non-standard targets. The IR printer currently does not +/// print anything when the default address space is attached to an instruction or value, and values will still +/// report being assigned to that space. However, these values are still subject to the backend's interpretation +/// of the data layout string overrides and as such may not always reside in the default address space when +/// it comes time to codegen them. +/// +/// Restrictions +/// ============ +/// +/// There are currently a number of artificial restrictions on values and operations that have non-default +/// address spaces: +/// - A `bitcast` between two pointer values residing in different address spaces, even if those two +/// values have the same size, is always an illegal operation. Use an `addrspacecast` instead or +/// always use `IRBuilder.buildPointerCast(of:to:name:)` to get the correct operation. +/// - The so-called "null pointer" has a bit value that may differ from address space to address space. This +/// exposes bugs in optimizer passes and lowerings that did not consider this possibility. +/// - A pointer value may not necessarily "round-trip" when converted between address spaces, even if +/// annotated `nonnull` and `dereferenceable`. This is especially true of non-integral pointer types. +/// - Though the zero address space is the default, many backends and some errant passes interpret this to +/// mean a "lack of address space" and may miscompile code with pointers in mixed address spaces. +/// - A number of intriniscs that operate on memory currently do not support a non-default address space. +/// - The address space is ultimately an integer value and in theory an address space identifier may take on +/// any value. In practice, LLVM guarantees only 24 bits of precision, though higher address space +/// identifiers may succeed in being properly represented. +public struct AddressSpace: Equatable { + let rawValue: Int + + /// LLVM's default address space. + public static let zero = AddressSpace(0) + + /// Creates and initializes an address space with the given identifier. + /// - Parameter identifier: The raw, integral address space identifier. + public init(_ identifier: Int) { + self.rawValue = identifier + } +} diff --git a/Sources/LLVM/Alias.swift b/Sources/LLVM/Alias.swift index 856cc0a8..5609b51a 100644 --- a/Sources/LLVM/Alias.swift +++ b/Sources/LLVM/Alias.swift @@ -3,7 +3,30 @@ import cllvm #endif /// An `Alias` represents a global alias in an LLVM module - a new symbol and -/// corresponding metadata for an existing position +/// corresponding metadata for an existing global value. +/// +/// An `Alias`, unlike a function or global variable declaration, does not +/// create any new data in the resulting object file. It is merely a new name +/// for an existing symbol or constant. The aliased value (the aliasee) must +/// be either another global value like a function, global variable, or even +/// another alias, or it must be a constant expression. +/// +/// Linkers make no guarantees that aliases will be preserved in the final +/// object file. Aliases where the address is known to be relevant should be +/// marked with the appropriate `UnnamedAddressKind` value. If this value is +/// not `none`, the alias is guaranteed to have the same address as the aliasee. +/// Else, the alias is guaranteed to point to the same content as the aliasee, +/// but may reside at a different address. +/// +/// If the aliasee is a constant value, LLVM places additional restrictions on +/// its content in order to maintain compatibility with the expected behavior of +/// most linkers: +/// +/// - The constant expression may not involve aliases with weak linkage. Such +/// weak aliases cannot be guaranteed to be stable in the final object file. +/// - The constant expression may not involve global values requiring a +/// relocation such as a global function or global variable declared but not +/// defined within its module. public struct Alias: IRGlobal { internal let llvm: LLVMValueRef @@ -11,4 +34,24 @@ public struct Alias: IRGlobal { public func asLLVM() -> LLVMValueRef { return llvm } + + /// The target value of this alias. + /// + /// The aliasee is required to be another global value or constant + public var aliasee: IRValue { + get { return LLVMAliasGetAliasee(llvm) } + set { LLVMAliasSetAliasee(llvm, newValue.asLLVM()) } + } + + /// Retrieves the previous alias in the module, if there is one. + public func previous() -> Alias? { + guard let previous = LLVMGetPreviousGlobalAlias(llvm) else { return nil } + return Alias(llvm: previous) + } + + /// Retrieves the next alias in the module, if there is one. + public func next() -> Alias? { + guard let next = LLVMGetNextGlobalAlias(llvm) else { return nil } + return Alias(llvm: next) + } } diff --git a/Sources/LLVM/Arbitrary.swift b/Sources/LLVM/Arbitrary.swift new file mode 100644 index 00000000..e73bd1e9 --- /dev/null +++ b/Sources/LLVM/Arbitrary.swift @@ -0,0 +1,1047 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +/// A value implementing arbitrary precision integer arithmetic. +/// +/// `APInt` is a functional replacement for common case unsigned integer type +/// like `UInt` or `UInt64`, but also allows non-byte-width +/// integer sizes and large integer value types such as 3-bits, 15-bits, or more +/// than 64-bits of precision. `APInt` provides a variety of arithmetic +/// operators and methods to manipulate integer values of any bit-width. It +/// supports both the typical integer arithmetic and comparison operations as +/// well as bitwise manipulation. +public struct APInt: IRConstant { + /// The underlying word size. + public typealias Word = UInt64 + + private enum Impl { + case single(Word) + case many([Word]) + } + + private var value: Impl + + /// The bitwidth of this integer. + public private(set) var bitWidth: Int + + fileprivate init(raw values: [Word], _ bits: Int) { + self.value = .many(values) + self.bitWidth = bits + } + + private mutating func clearUnusedBits() { + // Compute how many bits are used in the final word + let wordBits = ((bitWidth - 1) % bitsPerWord) + 1 + + // Mask out the high bits. + let mask = Word.max >> (bitsPerWord - wordBits) + switch self.value { + case let .single(val): + self.value = .single(val & mask) + case var .many(vals): + vals[vals.endIndex - 1] &= mask + self.value = .many(vals) + } + } + + public func asLLVM() -> LLVMValueRef { + let type = IntType(width: self.bitWidth, in: .global) + switch self.value { + case let .single(val): + return type.constant(val).asLLVM() + case let .many(vals): + let cnt = vals.count + return vals.withUnsafeBufferPointer { (words) -> LLVMValueRef in + LLVMConstIntOfArbitraryPrecision(type.asLLVM(), UInt32(cnt), words.baseAddress) + } + } + } +} + +// Mark: Value Constructors + +extension APInt { + /// Creates and initializes a new `APInt` with a bitwidth of one and a value + /// of zero. + public init() { + self.bitWidth = 1 + self.value = .single(0) + } + + /// Creates and initializes a new `APInt` with a given bit width, value, and + /// signedness. + /// + /// - Parameters: + /// - numBits: The bit width of the integer. + /// - value: The value of the integer. + /// - signed: If `true`, treat the most significant bit at the given bit + /// width as a sign bit. Defaults to `false`. + public init(width numBits: Int, value: UInt64, signed: Bool = false) { + precondition(numBits > 0) + self.bitWidth = numBits + if numBits <= bitsPerWord { + self.value = .single(value) + } else { + let numWords = requiredWords(for: numBits) + var values = [Word](repeating: 0, count: numWords) + values[0] = value + if signed && Int64(bitPattern: value) < 0 { + for i in 1.. 0) + self.bitWidth = numBits + if numBits <= bitsPerWord { + self.value = .single(values[0]) + } else { + let numWords = requiredWords(for: numBits) + var dst = [Word](repeating: 0, count: numWords) + for i in 0.. Bool { + precondition(lhs.bitWidth == rhs.bitWidth) + switch (lhs.value, rhs.value) { + case let (.single(vall), .single(valr)): + return vall == valr + case let (.many(vall), .many(valr)): + return vall == valr + default: + fatalError("Representation mismatch") + } + } + + public static func < (lhs: APInt, rhs: APInt) -> Bool { + precondition(lhs.bitWidth == rhs.bitWidth) + switch (lhs.value, rhs.value) { + case let (.single(vall), .single(valr)): + return vall < valr + case let (.many(vall), .many(valr)): + for i in (0..(exactly source: T) where T : BinaryInteger { + guard let val = UInt64(exactly: source) else { + return nil + } + self.init(integerLiteral: val) + } + + /// Returns the result of performing a bitwise AND operation on the two + /// given values. + public static func & (lhs: APInt, rhs: APInt) -> APInt { + var lhs = lhs + lhs &= rhs + return lhs + } + + /// Stores the result of performing a bitwise AND operation on the two given + /// values in the left-hand-side variable. + public static func &= (lhs: inout APInt, rhs: APInt) { + precondition(lhs.bitWidth == rhs.bitWidth) + switch (lhs.value, rhs.value) { + case let (.single(vall), .single(valr)): + lhs.value = .single(vall & valr) + case let (.many(vall), .many(valr)): + var dst = [APInt.Word](vall) + for i in 0.. APInt { + var lhs = lhs + lhs |= rhs + return lhs + } + + /// Stores the result of performing a bitwise OR operation on the two given + /// values in the left-hand-side variable. + public static func |= (lhs: inout APInt, rhs: APInt) { + precondition(lhs.bitWidth == rhs.bitWidth) + switch (lhs.value, rhs.value) { + case let (.single(vall), .single(valr)): + lhs.value = .single(vall | valr) + case let (.many(vall), .many(valr)): + var dst = [APInt.Word](vall) + for i in 0.. APInt { + var lhs = lhs + lhs ^= rhs + return lhs + } + + /// Stores the result of performing a bitwise XOR operation on the two given + /// values in the left-hand-side variable. + public static func ^= (lhs: inout APInt, rhs: APInt) { + precondition(lhs.bitWidth == rhs.bitWidth) + switch (lhs.value, rhs.value) { + case let (.single(vall), .single(valr)): + lhs.value = .single(vall ^ valr) + case let (.many(vall), .many(valr)): + var dst = [APInt.Word](vall) + for i in 0.. APInt { + var lhs = lhs + lhs += rhs + return lhs + } + + public static func += (lhs: inout APInt, rhs: APInt) { + precondition(lhs.bitWidth == rhs.bitWidth) + switch (lhs.value, rhs.value) { + case let (.single(vall), .single(valr)): + lhs.value = .single(vall + valr) + lhs.clearUnusedBits() + case let (.many(vall), .many(valr)): + var dst = [APInt.Word](vall) + var carry: UInt64 = 0 + for i in 0.. APInt { + var lhs = lhs + lhs -= rhs + return lhs + } + + public static func -= (lhs: inout APInt, rhs: APInt) { + precondition(lhs.bitWidth == rhs.bitWidth) + switch (lhs.value, rhs.value) { + case let (.single(vall), .single(valr)): + lhs.value = .single(vall - valr) + lhs.clearUnusedBits() + case let (.many(vall), .many(valr)): + var dst = [APInt.Word](vall) + var carry: UInt64 = 0 + for i in 0..= l) ? 1 : 0 + } else { + dst[i] -= valr[i] + carry = (dst[i] > l) ? 1 : 0 + } + } + lhs.value = .many(dst) + lhs.clearUnusedBits() + default: + fatalError("Representation mismatch") + } + } + + public var magnitude: APInt { + return self + } + + public static func * (lhs: APInt, rhs: APInt) -> APInt { + var lhs = lhs + lhs *= rhs + return lhs + } + + public static func *= (lhs: inout APInt, rhs: APInt) { + precondition(lhs.bitWidth == rhs.bitWidth) + switch (lhs.value, rhs.value) { + case let (.single(vall), .single(valr)): + lhs.value = .single(vall * valr) + lhs.clearUnusedBits() + case let (.many(vall), .many(valr)): + let numWords = vall.count + var dst = [APInt.Word](repeating: 0, count: numWords) + + var carry: APInt.Word = 0 + for i in 0..= vall[i] + UInt64(srcParts)) + assert(dstParts <= srcParts + 1) + + let n = min(dstParts, srcParts) + + for i in 0.. APInt { + var lhs = lhs + lhs <<= amount + return lhs + } + + /// Stores the result of shifting a value’s binary representation the + /// specified number of digits to the left in the left-hand-side variable. + public static func <<= (lhs: inout APInt, amount: UInt64) { + precondition(amount <= lhs.bitWidth) + switch lhs.value { + case let .single(val): + if amount == lhs.bitWidth { + lhs.value = .single(0) + } else { + lhs.value = .single(val << amount) + } + case let .many(vall): + guard amount > 0 else { + return + } + + var dst = [APInt.Word](vall) + let numWords = vall.count + + let (interPartShift, bitShift) = Int(amount).quotientAndRemainder(dividingBy: bitsPerWord) + let wordShift = min(interPartShift, numWords) + + // Fastpath for moving by whole words. + if bitShift == 0 { + for (src, dest) in (wordShift..<(numWords-wordShift)).enumerated() { + dst[src] = dst[dest] + } + } else { + for i in (wordShift.. wordShift { + dst[i] = dst[i - wordShift - 1] >> (bitsPerWord - bitShift) + } + } + } + + // Fill in the remainder with 0s. + for i in 0.. APInt { + var lhs = self + lhs.logicallyShiftRight(by: amount) + return lhs + } + + /// Logically shift the value right by the given amount. + /// + /// - Parameter amount: The amount to shift right by. + public mutating func logicallyShiftRight(by amount: UInt64) { + assert(amount <= self.bitWidth) + switch self.value { + case let .single(val): + if amount == self.bitWidth { + self.value = .single(0) + } else { + self.value = .single(val >> amount) + } + case let .many(vals): + guard amount > 0 else { + return + } + + var dst = [APInt.Word](vals) + + let (interPartShift, bitShift) = Int(amount).quotientAndRemainder(dividingBy: bitsPerWord) + let wordShift = min(interPartShift, vals.count) + + + let wordsToMove = dst.count - wordShift + // Fastpath for moving by whole words. + if bitShift == 0 { + for (src, dest) in (wordShift..> bitShift + if i + 1 != wordsToMove { + dst[i] |= dst[i + wordShift + 1] << (bitsPerWord - bitShift) + } + } + } + + // Fill in the remainder with 0s. + for i in wordsToMove..> (64 - self.bitWidth) + case let .many(vals): + guard (self.bitWidth - self.leadingZeroBitCount) <= 64 else { + return nil + } + return Int64(bitPattern: vals[0]) + } + } +} + +/// MARK: Bit-Level Information + +extension APInt { + /// Returns `true` if the most significant bit of this value is set. + /// + /// Note: This may return `true` even if you did not explicitly construct + /// a signed `APInt`. + public var isNegative: Bool { + switch self.value { + case let .single(val): + let msb = UInt64(1) << (bitsPerWord - (64 - self.bitWidth + 1)) + return (val & msb) == 1 + case let .many(vals): + let msb = UInt64(1) << (bitsPerWord - (64 - self.bitWidth + 1)) + return (vals[vals.endIndex - 1] & msb) == 1 + } + } + + /// Returns `true` if all bits are ones. + public var areAllBitsSet: Bool { + switch self.value { + case let .single(val): + return val == (Word.max >> (bitsPerWord - bitWidth)) + case let .many(vals): + var oneCount = 0 + var i = 0 + let numWords = requiredWords(for: self.bitWidth) + while i < numWords && vals[i] == Word.max { + defer { i += 1 } + oneCount += bitsPerWord + } + if i < numWords { + // Add the trailing 1 bit count + oneCount += (~vals[i]).leadingZeroBitCount + } + assert(oneCount <= self.bitWidth) + return oneCount == self.bitWidth + } + } + + /// The number of leading zeros in this value’s binary representation. + public var leadingZeroBitCount: Int { + switch self.value { + case let .single(val): + let unusedBits = bitsPerWord - self.bitWidth + return val.leadingZeroBitCount - unusedBits + case let .many(vals): + var count = 0 + for v in vals.reversed() { + guard v == 0 else { + count += v.leadingZeroBitCount + break + } + count += bitsPerWord + } + // Adjust for unused bits in the most significant word (they are zero). + let mod = self.bitWidth % bitsPerWord + count -= mod > 0 ? bitsPerWord - mod : 0 + return count + } + } + + + /// The number of leading ones in this value’s binary representation. + public var leadingNonZeroBitCount: Int { + switch self.value { + case let .single(val): + return (~(val << (bitsPerWord - self.bitWidth))).leadingZeroBitCount + case let .many(vals): + var highWordBits = self.bitWidth % bitsPerWord + var shift: Int + if highWordBits == 0 { + highWordBits = bitsPerWord + shift = 0 + } else { + shift = bitsPerWord - highWordBits + } + let tail = requiredWords(for: self.bitWidth) - 1 + var count = (~(vals[tail] << shift)).leadingZeroBitCount + if count == highWordBits { + for j in (0..) { + precondition(range.upperBound <= self.bitWidth) + precondition(range.lowerBound <= self.bitWidth) + precondition(range.lowerBound <= range.upperBound) + guard range.lowerBound != range.upperBound else { + return + } + + var mask: Word = Word.max >> (bitsPerWord - (range.upperBound - range.lowerBound)) + mask <<= range.lowerBound + switch self.value { + case let .single(val): + self.value = .single(val | mask) + case var .many(vals) where range.lowerBound < bitsPerWord && range.upperBound <= bitsPerWord: + vals[0] |= mask + self.value = .many(vals) + case var .many(vals): + let (loWord, loShift) = range.lowerBound.quotientAndRemainder(dividingBy: bitsPerWord) + let (hiWord, hiShift) = range.upperBound.quotientAndRemainder(dividingBy: bitsPerWord) + + // If hiBit is not aligned, we need a high mask. + var loMask = Word.max << loShift + if hiShift != 0 { + let hiMask = Word.max >> (bitsPerWord - hiShift) + if hiWord == loWord { + loMask &= hiMask + } else { + vals[hiWord] |= hiMask + } + } + vals[loWord] |= loMask + + // Fill any words between loWord and hiWord with all ones. + if loWord < hiWord { + for word in (loWord + 1)..) { + self.setBits(range.lowerBound...range.upperBound - 1) + } + + /// Sets all bits in the given range to one in this value's binary + /// representation. + /// + /// - Parameters: + /// - range: The range of bits to flip. + public mutating func setBits(_ range: PartialRangeUpTo) { + self.setBits(0...range.upperBound - 1) + } + + /// Sets all bits in the given range to one in this value's binary + /// representation. + /// + /// - Parameters: + /// - range: The range of bits to flip. + public mutating func setBits(_ range: PartialRangeThrough) { + self.setBits(0...range.upperBound) + } + + /// Sets all bits in the given range to one in this value's binary + /// representation. + /// + /// - Parameters: + /// - range: The range of bits to flip. + public mutating func setBits(_ range: PartialRangeFrom) { + self.setBits(range.lowerBound...self.bitWidth) + } + + /// Clears all bits to one in this value's binary representation. + public mutating func clearAllBits() { + switch self.value { + case .single(_): + self.value = .single(0) + case .many(_): + self.value = .many([Word](repeating: 0, count: requiredWords(for: self.bitWidth))) + } + } + + /// Sets the bit at the given position to zero. + /// + /// - Parameters: + /// - position: The position of the bit to zero. + public mutating func clearBit(_ position: Int) { + precondition(0 <= position) + precondition(position < self.bitWidth) + let mask: Word = ~((1 as Word) << UInt64(position % bitsPerWord)) + switch self.value { + case let .single(val): + self.value = .single(val | mask) + case var .many(vals): + vals[position % bitsPerWord] |= mask + self.value = .many(vals) + } + } + + /// Clears the sign bit in this value's binary representation. + public mutating func clearSignBit() { + self.clearBit(self.bitWidth - 1) + } +} + +/// MARK: Resizing Operations + +extension APInt { + /// Truncates the integer to a given bit width. + /// + /// - Parameter width: The new width to truncate towards. This width cannot + /// exceed the current width of the integer. + /// - Returns: An integer of the given bit width that has been truncated. + public func truncate(to width: Int) -> APInt { + precondition(width < self.bitWidth) + precondition(width > 0) + + if width <= bitsPerWord { + switch self.value { + case let .single(val): + return APInt(width: width, value: val) + case let .many(vals): + return APInt(width: width, values: vals) + } + } + + switch self.value { + case let .single(val): + return APInt(width: width, value: val) + case let .many(vals): + let numWords = requiredWords(for: self.bitWidth) + var dst = [APInt.Word](repeating: 0, count: numWords) + + // Copy full words. + for i in 0..<(width / bitsPerWord) { + dst[i] = vals[i] + } + + // Truncate and copy any partial word. + let bits = (0 - width) % bitsPerWord + if bits != 0 { + let partWidth = width / bitsPerWord + dst[partWidth - 1] = (vals[partWidth - 1] << bits) >> bits + } + return APInt(raw: dst, width) + } + } + + /// Zero extends the integer to a given bit width. + /// + /// - Parameter width: The width to zero-extend the integer to. This value + /// may not be smaller than the current width of the + /// integer. + /// - Returns: An integer of the given bit width that has been zero-extended. + public func zeroExtend(to width: Int) -> APInt { + precondition(width > self.bitWidth) + + switch self.value { + case let .single(val) where width <= bitsPerWord: + return APInt(width: width, value: val) + case let .single(val): + var dst = [APInt.Word](repeating: 0, count: requiredWords(for: width)) + dst[0] = val + return APInt(raw: dst, width) + case let .many(vals): + var dst = [APInt.Word](repeating: 0, count: requiredWords(for: width)) + for i in 0.. APInt { + precondition(width > self.bitWidth) + + switch self.value { + case let .single(val) where width <= bitsPerWord: + let ext = Int64(truncatingIfNeeded: (val << (64 - self.bitWidth))) >> (64 - self.bitWidth) + return APInt(width: width, value: UInt64(bitPattern: ext)) + case let .single(val): + var dst = [APInt.Word](repeating: 0, count: requiredWords(for: width)) + let b = ((self.bitWidth - 1) % bitsPerWord) + 1 + let ext = Int64(truncatingIfNeeded: (val << (64 - b))) >> (64 - b) + dst[0] = UInt64(bitPattern: ext) + + for i in 0..> (64 - b) + dst[vals.count - 1] = UInt64(bitPattern: ext) + + for i in vals.count..<(dst.count - vals.count) { + dst[i] = self.isNegative ? UInt64(bitPattern: -1) : 0 + } + var int = APInt(raw: dst, width) + int.clearUnusedBits() + return int + } + } + + /// Zero extends or truncates the integer to the given width. + /// + /// If the given bit width exceeds the current bit width, the value is + /// zero-extended. Else if the given bit width is less than the current + /// bit width, the value is truncated. + /// + /// If the given bit width matches the current bit width, this operation is + /// a no-op. + /// + /// - Parameter width: The width to zero extend or truncate to. + /// - Returns: An integer that has been zero extended or truncated to fit + /// the given bit width. + public func zeroExtendOrTruncate(to width: Int) -> APInt { + if self.bitWidth < width { + return self.zeroExtend(to: width) + } + if self.bitWidth > width { + return self.truncate(to: width) + } + return self + } + + /// Sign extends or truncates the integer to the given width. + /// + /// If the given bit width exceeds the current bit width, the value is + /// sign-extended. Else if the given bit width is less than the current + /// bit width, the value is truncated. + /// + /// If the given bit width matches the current bit width, this operation is + /// a no-op. + /// + /// - Parameter width: The width to sign extend or truncate to. + /// - Returns: An integer that has been sign extended or truncated to fit + /// the given bit width. + public func signExtendOrTruncate(to width: Int) -> APInt { + if self.bitWidth < width { + return self.signExtend(to: width) + } + if self.bitWidth > width { + return self.truncate(to: width) + } + return self + } + + /// Toggle every bit in this integer to its opposite value. + public mutating func flipAll() { + switch self.value { + case let .single(val): + self.value = .single(val ^ Word.max) + self.clearUnusedBits() + case let .many(vals): + var dst = [APInt.Word](vals) + for i in 0.. APInt { + var cpy = val + cpy.flipAll() + return cpy + } +} + +private let wordSize = MemoryLayout.size +private let bitsPerWord = MemoryLayout.size * CChar.bitWidth + +private func lowHalf(_ part: APInt.Word) -> APInt.Word { + return part & APInt.Word.max >> (bitsPerWord - (bitsPerWord / 2)) +} + +private func highHalf(_ part: APInt.Word) -> APInt.Word { + return part >> (bitsPerWord / 2) +} + +private func requiredWords(for bitWidth: Int) -> Int { + return (bitWidth + bitsPerWord - 1) / bitsPerWord +} diff --git a/Sources/LLVM/ArrayType.swift b/Sources/LLVM/ArrayType.swift index 698b29ec..f199486b 100644 --- a/Sources/LLVM/ArrayType.swift +++ b/Sources/LLVM/ArrayType.swift @@ -24,10 +24,10 @@ public struct ArrayType: IRType { /// - parameter type: The type of the provided IR values. /// /// - returns: A constant array value containing the given values. - public static func constant(_ values: [IRValue], type: IRType) -> IRValue { + public static func constant(_ values: [IRValue], type: IRType) -> IRConstant { var vals = values.map { $0.asLLVM() as Optional } return vals.withUnsafeMutableBufferPointer { buf in - return LLVMConstArray(type.asLLVM(), buf.baseAddress, UInt32(buf.count)) + return Constant(llvm: LLVMConstArray(type.asLLVM(), buf.baseAddress, UInt32(buf.count))) } } @@ -39,9 +39,9 @@ public struct ArrayType: IRType { /// /// - returns: A null terminated constant array value containing /// `string.utf8.count + 1` i8's. - public static func constant(string: String, in context: Context = .global) -> IRValue { + public static func constant(string: String, in context: Context = .global) -> IRConstant { let length = string.utf8.count - return LLVMConstStringInContext(context.llvm, string, UInt32(length), 0) + return Constant(llvm: LLVMConstStringInContext(context.llvm, string, UInt32(length), 0)) } /// Retrieves the underlying LLVM type object. @@ -49,3 +49,9 @@ public struct ArrayType: IRType { return LLVMArrayType(elementType.asLLVM(), UInt32(count)) } } + +extension ArrayType: Equatable { + public static func == (lhs: ArrayType, rhs: ArrayType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() + } +} diff --git a/Sources/LLVM/AttachedMetadata.swift b/Sources/LLVM/AttachedMetadata.swift new file mode 100644 index 00000000..75b1f04e --- /dev/null +++ b/Sources/LLVM/AttachedMetadata.swift @@ -0,0 +1,711 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +extension Context { + /// Searches for and retrieves a metadata kind with the given name in this + /// context. If none is found, one with that name is created and its unique + /// identifier is returned. + public func metadataKind(named name: String, in context: Context = .global) -> UInt32 { + return LLVMGetMDKindIDInContext(context.llvm, name, UInt32(name.count)) + } +} + +extension IRGlobal { + /// Retrieves all metadata entries attached to this global value. + public var metadata: AttachedMetadata { + var count = 0 + let ptr = LLVMGlobalCopyAllMetadata(self.asLLVM(), &count) + return AttachedMetadata(llvm: ptr, bounds: count) + } + + /// Sets a metadata attachment, erasing the existing metadata attachment if + /// it already exists for the given kind. + /// + /// - Parameters: + /// - metadata: The metadata to attach to this global value. + /// - kind: The kind of metadata to attach. + public func addMetadata(_ metadata: IRMetadata, kind: AttachedMetadata.PinnedKind) { + LLVMGlobalSetMetadata(self.asLLVM(), kind.rawValue, metadata.asMetadata()) + } + + /// Sets a metadata attachment, erasing the existing metadata attachment if + /// it already exists for the given kind. + /// + /// - Parameters: + /// - metadata: The metadata to attach to this global value. + /// - kind: The kind of metadata to attach. + public func addMetadata(_ metadata: IRMetadata, kind: UInt32) { + LLVMGlobalSetMetadata(self.asLLVM(), kind, metadata.asMetadata()) + } + + /// Removes all metadata attachments from this value. + public func removeAllMetadata() { + LLVMGlobalClearMetadata(self.asLLVM()) + } + + /// Erases a metadata attachment of the given kind if it exists. + /// + /// - Parameter kind: The kind of the metadata to remove. + public func eraseAllMetadata(of kind: UInt32) { + LLVMGlobalEraseMetadata(self.asLLVM(), kind) + } +} + +extension IRInstruction { + /// Retrieves all metadata entries attached to this instruction. + public var metadata: AttachedMetadata { + var count = 0 + let ptr = LLVMGlobalCopyAllMetadata(self.asLLVM(), &count) + return AttachedMetadata(llvm: ptr, bounds: count) + } + + /// Sets a metadata attachment, erasing the existing metadata attachment if + /// it already exists for the given kind. + /// + /// - Parameters: + /// - metadata: The metadata to attach to this global value. + /// - kind: The kind of metadata to attach. + public func addMetadata(_ metadata: IRMetadata, kind: AttachedMetadata.PinnedKind) { + LLVMSetMetadata(self.asLLVM(), kind.rawValue, LLVMMetadataAsValue(self.type.context.llvm, metadata.asMetadata())) + } + + /// Sets a metadata attachment, erasing the existing metadata attachment if + /// it already exists for the given kind. + /// + /// - Parameters: + /// - metadata: The metadata to attach to this global value. + /// - kind: The kind of metadata to attach. + public func addMetadata(_ metadata: IRMetadata, kind: UInt32) { + LLVMSetMetadata(self.asLLVM(), kind, LLVMMetadataAsValue(self.type.context.llvm, metadata.asMetadata())) + } +} + +/// Represents a sequence of metadata entries attached to a global value that +/// are uniqued by kind. +public class AttachedMetadata { + /// Metadata kinds that are known to LLVM. + public enum PinnedKind: UInt32 { + /// Debug information metadata. + /// + /// `dbg` metadata is used to record primary debugging source-level + /// debugging information for values and functions. + case dbg = 0 + /// Type Based Alias Analysis metadata. + /// + /// In LLVM IR, memory does not have types, so LLVM’s own type system is not + /// suitable for doing type based alias analysis (TBAA). Instead, metadata + /// is added to the IR to describe a type system of a higher level language. + /// This can be used to implement C/C++ strict type aliasing rules, but it + /// can also be used to implement custom alias analysis behavior for other + /// languages. + /// + /// To read more about how to do TBAA in LLVM, see the + /// [Language Reference](https://llvm.org/docs/LangRef.html#tbaa-metadata). + case tbaa = 1 + /// Profiling metadata. + /// + /// `prof` metadata is used to record profile data in the IR. The first + /// operand of the metadata node indicates the profile metadata type. There + /// are currently 3 types: `branch_weights`, `function_entry_count`, + /// and `VP`. + /// + /// Branch weight metadata attached to a `branch`, `select`, `switch` or + /// `call` instruction represents the likeliness of the associated branch + /// being taken. + /// + /// Function entry count metadata can be attached to function definitions to + /// record the number of times the function is called. Used with + /// block frequency information, it is also used to derive the basic block + /// profile count. + /// + /// VP (value profile) metadata can be attached to instructions that have + /// value profile information. Currently this is indirect calls (where it + /// records the hottest callees) and calls to memory intrinsics such as + /// `memcpy`, `memmove`, and `memset` (where it records the hottest byte + /// lengths). + /// + /// Each VP metadata node contains the “VP” string, then an unsigned 32-bit + /// value for the value profiling kind, an unsigned 64-bit value for the + /// total number of times the instruction is executed, followed by an + /// unsigned 64-bit value and execution count pairs. The value profiling + /// kind is 0 for indirect call targets and 1 for memory operations. For + /// indirect call targets, each profile value is a hash of the callee + /// function name, and for memory operations each value is the byte length. + /// + /// Note that the value counts do not need to add up to the total count + /// listed in the third operand (in practice only the top hottest values + /// are tracked and reported). + /// + /// For example: + /// + /// call void %f(), !prof !1 + /// !1 = !{!"VP", i32 0, i64 1600, i64 7651369219802541373, i64 1030, i64 -4377547752858689819, i64 410} + /// + /// Note that the VP type is 0 (the second operand), which indicates this is + /// an indirect call value profile data. The third operand indicates that + /// the indirect call executed 1600 times. The 4th and 6th operands give the + /// hashes of the 2 hottest target functions’ names (this is the same hash + /// used to represent function names in the profile database), and the 5th + /// and 7th operands give the execution count that each of the respective + /// prior target functions was called. + case prof = 2 + /// Floating-point math metadata. + /// + /// `fpmath` metadata may be attached to any instruction of floating-point + /// type. It can be used to express the maximum acceptable error in the + /// result of that instruction, in ULPs, thus potentially allowing the + /// compiler to use a more efficient but less accurate method of computing + /// it. ULP is defined as follows: + /// + /// If `x` is a real number that lies between two finite consecutive + /// floating-point numbers `a` and `b`, without being equal to one of them, + /// then `ulp(x) = |b - a|`, otherwise `ulp(x)` is the distance between the + /// two non-equal finite floating-point numbers nearest `x`. + /// Moreover, `ulp(NaN)` is `NaN`. + /// + /// The metadata node shall consist of a single positive float type number + /// representing the maximum relative error, for example: + /// + /// !0 = !{ float 2.5 } ; maximum acceptable inaccuracy is 2.5 ULPs + case fpmath = 3 + /// Range metadata. + /// + /// Range metadata may be attached only to load, call and invoke of integer + /// types. It expresses the possible ranges the loaded value or the value + /// returned by the called function at this call site is in. If the loaded + /// or returned value is not in the specified range, the behavior is + /// undefined. The ranges are represented with a flattened list of integers. + /// The loaded value or the value returned is known to be in the union of + /// the ranges defined by each consecutive pair. Each pair has the + /// following properties: + /// + /// - The type must match the type loaded by the instruction. + /// - The pair `a,b` represents the range `[a,b)`. + /// - Both `a` and `b` are constants. + /// - The range is allowed to wrap. + /// - The range should not represent the full or empty set. + /// That is, `a != b`. + /// - In addition, the pairs must be in signed order of the lower bound and + /// they must be non-contiguous. + /// + /// For example: + /// + /// %a = load i8, i8* %x, align 1, !range !0 ; Can only be 0 or 1 + /// %b = load i8, i8* %y, align 1, !range !1 ; Can only be 255 (-1), 0 or 1 + /// %c = call i8 @foo(), !range !2 ; Can only be 0, 1, 3, 4 or 5 + /// %d = invoke i8 @bar() to label %cont + /// unwind label %lpad, !range !3 ; Can only be -2, -1, 3, 4 or 5 + /// ... + /// !0 = !{ i8 0, i8 2 } + /// !1 = !{ i8 255, i8 2 } + /// !2 = !{ i8 0, i8 2, i8 3, i8 6 } + /// !3 = !{ i8 -2, i8 0, i8 3, i8 6 } + case range = 4 + /// Type Based Alias Analysis struct metadata. + /// + /// The `llvm.memcpy.*` family of instrinsics is often used to implement + /// aggregate assignment operations in C and similar languages, however it + /// is defined to copy a contiguous region of memory, which is more than + /// strictly necessary for aggregate types which contain holes due to + /// padding. Also, it doesn’t contain any TBAA information about the fields + /// of the aggregate. + /// + /// `tbaa.struct` metadata can describe which memory subregions in a + /// `memcpy` are padding and what the TBAA tags of the struct are. + /// + /// The current metadata format is very simple. `tbaa.struct` metadata nodes + /// are a list of operands which are in conceptual groups of three. For each + /// group of three, the first operand gives the byte offset of a field in + /// bytes, the second gives its size in bytes, and the third gives its + /// tbaa tag. e.g.: + /// + /// !4 = !{ i64 0, i64 4, !1, i64 8, i64 4, !2 } + /// + /// This describes a struct with two fields: The first is at offset 0 bytes + /// with size 4 bytes, and has tbaa tag `!1`. The second is at offset 8 + /// bytes and has size 4 bytes and has tbaa tag !2. + /// + /// Note that the fields need not be contiguous. In this example, there is a + /// 4 byte gap between the two fields. This gap represents padding which + /// does not carry useful data and need not be preserved. + case tbaaStruct = 5 + /// Load addreess invariance metadata. + /// + /// If a load instruction tagged with the `invariant.load` metadata is + /// executed, the optimizer may assume the memory location referenced by the + /// load contains the same value at all points in the program where the + /// memory location is known to be dereferenceable; otherwise, the + /// behavior is undefined. + case invariantLoad = 6 + /// Alias scope metadata. + /// + /// `alias.scope` metadata provide the ability to specify generic `noalias` + /// memory-access sets. This means that some collection of memory access + /// instructions (loads, stores, memory-accessing calls, etc.) that carry + /// `noalias` metadata can specifically be specified not to alias with some + /// other collection of memory access instructions that carry `alias.scope` + /// metadata. Each type of metadata specifies a list of scopes where each + /// scope has an id and a domain. + /// + /// When evaluating an aliasing query, if for some domain, the set of scopes + /// with that domain in one instruction’s `alias.scope` list is a subset of + /// (or equal to) the set of scopes for that domain in another instruction’s + /// noalias list, then the two memory accesses are assumed not to alias. + /// + /// Because scopes in one domain don’t affect scopes in other domains, + /// separate domains can be used to compose multiple independent noalias + /// sets. This is used for example during inlining. As the noalias function + /// parameters are turned into noalias scope metadata, a new domain is used + /// every time the function is inlined. + /// + /// The metadata identifying each domain is itself a list containing one or + /// two entries. The first entry is the name of the domain. Note that if the + /// name is a string then it can be combined across functions and + /// translation units. A self-reference can be used to create globally + /// unique domain names. A descriptive string may optionally be provided as + /// a second list entry. + /// + /// The metadata identifying each scope is also itself a list containing two + /// or three entries. The first entry is the name of the scope. Note that if + /// the name is a string then it can be combined across functions and + /// translation units. A self-reference can be used to create globally + /// unique scope names. A metadata reference to the scope’s domain is the + /// second entry. A descriptive string may optionally be provided as a third + /// list entry. + /// + /// For example: + /// + /// ; Two scope domains: + /// !0 = !{!0} + /// !1 = !{!1} + /// + /// ; Some scopes in these domains: + /// !2 = !{!2, !0} + /// !3 = !{!3, !0} + /// !4 = !{!4, !1} + /// + /// ; Some scope lists: + /// !5 = !{!4} ; A list containing only scope !4 + /// !6 = !{!4, !3, !2} + /// !7 = !{!3} + /// + /// ; These two instructions don't alias: + /// %0 = load float, float* %c, align 4, !alias.scope !5 + /// store float %0, float* %arrayidx.i, align 4, !noalias !5 + /// + /// ; These two instructions also don't alias (for domain !1, the set of scopes + /// ; in the !alias.scope equals that in the !noalias list): + /// %2 = load float, float* %c, align 4, !alias.scope !5 + /// store float %2, float* %arrayidx.i2, align 4, !noalias !6 + /// + /// ; These two instructions may alias (for domain !0, the set of scopes in + /// ; the !noalias list is not a superset of, or equal to, the scopes in the + /// ; !alias.scope list): + /// %2 = load float, float* %c, align 4, !alias.scope !6 + /// store float %0, float* %arrayidx.i, align 4, !noalias !7 + case aliasScope = 7 + /// No-alias metadata. + /// + /// `noalias` metadata provide the ability to specify generic `noalias` + /// memory-access sets. This means that some collection of memory access + /// instructions (loads, stores, memory-accessing calls, etc.) that carry + /// `noalias` metadata can specifically be specified not to alias with some + /// other collection of memory access instructions that carry `alias.scope` + /// metadata. Each type of metadata specifies a list of scopes where each + /// scope has an id and a domain. + case noalias = 8 + /// Temporal metadata. + /// + /// The existence of the !nontemporal metadata on the instruction tells the + /// optimizer and code generator that this load is not expected to be reused + /// in the cache. The code generator may select special instructions to save + /// cache bandwidth, such as the `MOVNT` instruction on x86. + case nontemporal = 9 + /// Loop memory access metadata. + /// + /// If certain memory accesses within a loop are independent of each other + /// (that is, they have no loop-carried dependencies), and if these are the + /// only accesses in the loop, then tagging load/store instructions with + /// `llvm.mem.parallel_loop_access` signals to the optimizer that those + /// accesses can be vectorized. + case memParallelLoopAccess = 10 + /// Non-null metadata. + /// + /// This indicates that the parameter or return pointer is not null. This + /// attribute may only be applied to pointer typed parameters. This is not + /// checked or enforced by LLVM; if the parameter or return pointer is null, + /// the behavior is undefined. + /// + /// Note that the concept of a "null" pointer is address space dependent. it is + /// not necessarily the 0 bit-pattern. + case nonnull = 11 + /// Dereferenceable metadata. + /// + /// This indicates that the parameter or return pointer is dereferenceable. + /// This attribute may only be applied to pointer typed parameters. A + /// pointer that is dereferenceable can be loaded from speculatively without + /// a risk of trapping. The number of bytes known to be dereferenceable must + /// be provided in parentheses. It is legal for the number of bytes to be + /// less than the size of the pointee type. The `nonnull` attribute does not + /// imply dereferenceability (consider a pointer to one element past the end + /// of an array), however `dereferenceable` does imply `nonnull` in + /// the default address space. + case dereferenceable = 12 + /// Dereferenceable or null metadata. + /// + /// This indicates that the parameter or return value isn’t both non-null + /// and non-dereferenceable (up to a given number of bytes) at the same + /// time. All non-null pointers tagged with `dereferenceable_or_null` are + /// `dereferenceable`. For address space 0, `dereferenceable_or_null` + /// implies that a pointer is exactly one of `dereferenceable` or `null`, + /// and in other address spaces `dereferenceable_or_null` implies that a + /// pointer is at least one of `dereferenceable` or `null` (i.e. it may be + /// both `null` and `dereferenceable`). This attribute may only be applied + /// to pointer typed parameters. + case dereferenceableOrNull = 13 + /// Implicit checks metadata. + /// + /// Making null checks implicit is an aggressive optimization, and it can be + /// a net performance pessimization if too many memory operations end up + /// faulting because of it. A language runtime typically needs to ensure + /// that only a negligible number of implicit null checks actually fault + /// once the application has reached a steady state. A standard way of doing + /// this is by healing failed implicit null checks into explicit null checks + /// via code patching or recompilation. It follows that there are two + /// requirements an explicit null check needs to satisfy for it to be + /// profitable to convert it to an implicit null check: + /// + /// - The case where the pointer is actually null (i.e. the “failing” case) + /// is extremely rare. + /// - The failing path heals the implicit null check into an explicit null + /// check so that the application does not repeatedly page fault. + /// + /// The frontend is expected to mark branches that satisfy both conditions + /// using a `make.implicit` metadata node (the actual content of the + /// metadata node is ignored). Only branches that are marked with + /// `make.implicit` metadata are considered as candidates for conversion + /// into implicit null checks. + case makeImplicit = 14 + /// Unpredictable metadata. + /// + /// Unpredictable metadata may be attached to any `branch` or `switch` + /// instruction. It can be used to express the unpredictability of control + /// flow. Similar to the `llvm.expect` intrinsic, it may be used to alter + /// optimizations related to compare and branch instructions. The metadata + /// is treated as a boolean value; if it exists, it signals that the branch + /// or switch that it is attached to is completely unpredictable. + case unpredictable = 15 + /// Invariant group metadata. + /// + /// The experimental `invariant.group` metadata may be attached to + /// load/store instructions referencing a single metadata with no entries. + /// The existence of `invariant.group` metadata on the instruction tells the + /// optimizer that every load and store to the same pointer operand can be + /// assumed to load or store the same value. + /// + /// Pointers returned by `bitcast` or `getelementptr` with only zero indices + /// are considered the same. + /// + /// Examples: + /// + /// @unknownPtr = external global i8 + /// ... + /// %ptr = alloca i8 + /// store i8 42, i8* %ptr, !invariant.group !0 + /// call void @foo(i8* %ptr) + /// + /// %a = load i8, i8* %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change + /// call void @foo(i8* %ptr) + /// + /// %newPtr = call i8* @getPointer(i8* %ptr) + /// %c = load i8, i8* %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr + /// + /// %unknownValue = load i8, i8* @unknownPtr + /// store i8 %unknownValue, i8* %ptr, !invariant.group !0 ; Can assume that %unknownValue == 42 + /// + /// call void @foo(i8* %ptr) + /// %newPtr2 = call i8* @llvm.launder.invariant.group(i8* %ptr) + /// %d = load i8, i8* %newPtr2, !invariant.group !0 ; Can't step through launder.invariant.group to get value of %ptr + /// + /// ... + /// declare void @foo(i8*) + /// declare i8* @getPointer(i8*) + /// declare i8* @llvm.launder.invariant.group(i8*) + /// + /// !0 = !{} + /// + /// The `invariant.group` metadata must be dropped when replacing one pointer + /// by another based on aliasing information. This is because + /// `invariant.group` is tied to the SSA value of the pointer operand. + /// + /// %v = load i8, i8* %x, !invariant.group !0 + /// ; if %x mustalias %y then we can replace the above instruction with + /// %v = load i8, i8* %y + /// + /// Note that this is an experimental feature, which means that its + /// semantics might change in the future. + case invariantGroup = 16 + /// Alignment metadata. + /// + /// This indicates that the pointer value may be assumed by the optimizer to + /// have the specified alignment. If the pointer value does not have the + /// specified alignment, behavior is undefined. + case align = 17 + /// Loop identifier metadata. + /// + /// It is sometimes useful to attach information to loop constructs. + /// Currently, loop metadata is implemented as metadata attached to the + /// branch instruction in the loop latch block. This type of metadata refer + /// to a metadata node that is guaranteed to be separate for each loop. The + /// loop identifier metadata is specified with the name `llvm.loop`. + /// + /// The loop identifier metadata is implemented using a metadata that + /// refers to itself to avoid merging it with any other identifier + /// metadata, e.g., during module linkage or function inlining. That is, + /// each loop should refer to their own identification metadata even if + /// they reside in separate functions. The following example contains loop + /// identifier metadata for two separate loop constructs: + /// + /// !0 = !{!0} + /// !1 = !{!1} + /// + /// The loop identifier metadata can be used to specify additional per-loop + /// metadata. Any operands after the first operand can be treated as + /// user-defined metadata. For example the `llvm.loop.unroll.count` + /// suggests an unroll factor to the loop unroller: + /// + /// br i1 %exitcond, label %._crit_edge, label %.lr.ph, !llvm.loop !0 + /// ... + /// !0 = !{!0, !1} + /// !1 = !{!"llvm.loop.unroll.count", i32 4} + case loop = 18 + /// Type metadata. + /// + /// Type metadata is a mechanism that allows IR modules to co-operatively + /// build pointer sets corresponding to addresses within a given set of + /// globals. LLVM’s control flow integrity implementation uses this metadata + /// to efficiently check (at each call site) that a given address + /// corresponds to either a valid vtable or function pointer for a given + /// class or function type, and its whole-program devirtualization pass uses + /// the metadata to identify potential callees for a given virtual call. + /// + /// For more information, see [Type Metadata](https://www.llvm.org/docs/TypeMetadata.html). + case type = 19 + /// Section prefix metadata. + /// + /// LLVM allows an explicit section to be specified for functions. If the + /// target supports it, it will emit functions to the section specified. + /// Additionally, the function can be placed in a COMDAT. + case sectionPrefix = 20 + /// Absolute symbol metadata. + /// + /// `absolute_symbol` metadata may be attached to a global variable + /// declaration. It marks the declaration as a reference to an absolute + /// symbol, which causes the backend to use absolute relocations for the + /// symbol even in position independent code, and expresses the possible + /// ranges that the global variable’s address (not its value) is in, in the + /// same format as range metadata, with the extension that the pair + /// `all-ones,all-ones` may be used to represent the full set. + /// + /// For example (assuming 64-bit pointers): + /// + /// @a = external global i8, !absolute_symbol !0 ; Absolute symbol in range [0,256) + /// @b = external global i8, !absolute_symbol !1 ; Absolute symbol in range [0,2^64) + /// ... + /// !0 = !{ i64 0, i64 256 } + /// !1 = !{ i64 -1, i64 -1 } + case absoluteSymbol = 21 + /// Associated metadata. + /// + /// `associated` metadata may be attached to a global object declaration + /// with a single argument that references another global object. + /// + /// This metadata prevents discarding of the global object in linker GC + /// unless the referenced object is also discarded. The linker support for + /// this feature is spotty. For best compatibility, globals carrying this + /// metadata may also: + /// + /// - Be in a comdat with the referenced global. + /// - Be in `@llvm.compiler.used`. + /// - Have an explicit section with a name which is a valid C identifier. + /// + /// It does not have any effect on non-ELF targets. + /// + /// For example: + /// + /// $a = comdat any + /// @a = global i32 1, comdat $a + /// @b = internal global i32 2, comdat $a, section "abc", !associated !0 + /// !0 = !{i32* @a} + case associated = 22 + /// Callees metadata. + /// + /// Callees metadata may be attached to indirect call sites. If callees + /// metadata is attached to a call site, and any callee is not among the + /// set of functions provided by the metadata, the behavior is undefined. + /// + /// The intent of this metadata is to facilitate optimizations such as + /// indirect-call promotion. For example, in the code below, the call + /// instruction may only target the add or sub functions: + /// + /// %result = call i64 %binop(i64 %x, i64 %y), !callees !0 + /// ... + /// !0 = !{i64 (i64, i64)* @add, i64 (i64, i64)* @sub} + case callees = 23 + /// Irreducible loop metadata. + /// + /// `irr_loop` metadata may be attached to the terminator instruction of a + /// basic block that’s an irreducible loop header (note that an irreducible + /// loop has more than once header basic blocks.) If `irr_loop` metadata is + /// attached to the terminator instruction of a basic block that is not + /// really an irreducible loop header, the behavior is undefined. + /// + /// The intent of this metadata is to improve the accuracy of the block + /// frequency propagation. For example, in the code below, the block + /// `header0` may have a loop header weight (relative to the other headers + /// of the irreducible loop) of 100: + /// + /// header0: + /// ... + /// br i1 %cmp, label %t1, label %t2, !irr_loop !0 + /// ... + /// !0 = !{"loop_header_weight", i64 100} + /// + /// Irreducible loop header weights are typically based on profile data. + case irrLoop = 24 + /// Memory access group metadata. + /// + /// `llvm.access.group` metadata can be attached to any instruction that + /// potentially accesses memory. It can point to a single distinct metadata + /// node, which we call access group. This node represents all memory access + /// instructions referring to it via `llvm.access.group`. + /// + /// When an instruction belongs to multiple access groups, it can also point + /// to a list of accesses groups, illustrated by the following example: + /// + /// %val = load i32, i32* %arrayidx, !llvm.access.group !0 + /// ... + /// !0 = !{!1, !2} + /// !1 = distinct !{} + /// !2 = distinct !{} + /// + /// It is illegal for the list node to be empty since it might be confused + /// with an access group. + /// + /// The access group metadata node must be `distinct` to avoid collapsing + /// multiple access groups by content. An access group metadata node must + /// always be empty which can be used to distinguish an access group + /// metadata node from a list of access groups. Being empty avoids the + /// situation that the content must be updated which, because metadata is + /// immutable by design, would required finding and updating all references + /// to the access group node. + /// + /// The access group can be used to refer to a memory access instruction + /// without pointing to it directly (which is not possible in global + /// metadata). Currently, the only metadata making use of it is + /// `llvm.loop.parallel_accesses`. + case accessGroup = 25 + /// Callback metadata. + /// + /// Callback metadata may be attached to a function declaration, or + /// definition. The metadata describes how the arguments of a call to a + /// function are in turn passed to the callback function specified by the + /// metadata. Thus, the callback metadata provides a partial description of + /// a call site inside the function with regards to the arguments of a call + /// to the function. The only semantic restriction on the function itself is + /// that it is not allowed to inspect or modify arguments referenced in the + /// callback metadata as pass-through to the callback function. + /// + /// The function is not required to actually invoke the callback function + /// at runtime. However, the assumptions about not inspecting or modifying + /// arguments that would be passed to the specified callback function + /// still hold, even if the callback function is not dynamically invoked. + /// The function is allowed to invoke the callback function more than once + /// per invocation. The function is also allowed to invoke (directly or + /// indirectly) the function passed as a callback through another use. + /// Finally, the function is also allowed to relay the callback callee + /// invocation to a different thread. + /// + /// The metadata is structured as follows: At the outer level, callback + /// metadata is a list of callback encodings. Each encoding starts with a + /// constant `i64` which describes the argument position of the callback + /// function in the call to the function. The following elements, except + /// the last, describe what arguments are passed to the callback function. + /// Each element is again an `i64` constant identifying the argument of the + /// broker that is passed through, or `i64 -1` to indicate an unknown or + /// inspected argument. The order in which they are listed has to be the + /// same in which they are passed to the callback callee. The last element + /// of the encoding is a boolean which specifies how variadic arguments of + /// the broker are handled. If it is true, all variadic arguments of the + /// broker are passed through to the callback function after the arguments + /// encoded explicitly before. + /// + /// In the code below, the `pthread_create` function is marked as such a + /// function through the `!callback !1` metadata. In the example, there is + /// only one callback encoding, namely `!2`, associated with it. This + /// encoding identifies the callback function as the second argument + /// `(i64 2)` and the sole argument of the callback function + /// as the third `(i64 3)`. + /// + /// declare !callback !1 dso_local i32 @pthread_create(i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*) + /// ... + /// !2 = !{i64 2, i64 3, i1 false} + /// !1 = !{!2} + /// Another example is shown below. The callback callee is the second + /// argument of the `__kmpc_fork_call` function `(i64 2)`. The callee is + /// given two unknown values (each identified by a `i64 -1`) and afterwards + /// all variadic arguments that are passed to the `__kmpc_fork_call` call + /// (due to the final i1 true). + /// + /// declare !callback !0 dso_local void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) + /// ... + /// !1 = !{i64 2, i64 -1, i64 -1, i1 true} + /// !0 = !{!1} + case callback = 26 + } + + /// Represents an entry in the module flags structure. + public struct Entry { + fileprivate let base: AttachedMetadata + fileprivate let index: UInt32 + + /// The metadata kind associated with this global metadata. + public var kind: UInt32 { + return LLVMValueMetadataEntriesGetKind(self.base.llvm, self.index) + } + + /// The metadata value associated with this entry. + public var metadata: IRMetadata { + return AnyMetadata(llvm: LLVMValueMetadataEntriesGetMetadata(self.base.llvm, self.index)) + } + } + + private let llvm: OpaquePointer? + private let bounds: Int + fileprivate init(llvm: OpaquePointer?, bounds: Int) { + self.llvm = llvm + self.bounds = bounds + } + + /// Deinitialize this value and dispose of its resources. + deinit { + guard let ptr = llvm else { return } + LLVMDisposeValueMetadataEntries(ptr) + } + + /// Retrieves a flag at the given index. + /// + /// - Parameter index: The index to retrieve. + /// + /// - Returns: An entry describing the flag at the given index. + public subscript(_ index: Int) -> Entry { + precondition(index >= 0 && index < self.bounds, "Index out of bounds") + return Entry(base: self, index: UInt32(index)) + } + + /// Returns the number of metadata entries. + public var count: Int { + return self.bounds + } +} diff --git a/Sources/LLVM/BasicBlock.swift b/Sources/LLVM/BasicBlock.swift index 0e121e54..adcdc8f5 100644 --- a/Sources/LLVM/BasicBlock.swift +++ b/Sources/LLVM/BasicBlock.swift @@ -5,16 +5,70 @@ import cllvm /// A `BasicBlock` represents a basic block in an LLVM IR program. A basic /// block contains a sequence of instructions, a pointer to its parent block and /// its follower block, and an optional label that gives the basic block an -/// entry in the symbol table. +/// entry in the symbol table. Because of this label, the type of every basic +/// block is `LabelType`. /// /// A basic block can be thought of as a sequence of instructions, and indeed -/// its member instructions may be iterated over with a `for-in` loop. +/// its member instructions may be iterated over with a `for-in` loop. A well- +/// formed basic block has as its last instruction a "terminator" that produces +/// a transfer of control flow and possibly yields a value. All other +/// instructions in the middle of the basic block may not be "terminator" +/// instructions. Basic blocks are not required to be well-formed until +/// code generation is complete. /// -/// The first basic block in a function is special in two ways: it is -/// immediately executed on entrance to the function, and it is not allowed to -/// have predecessor basic blocks (i.e. there can not be any branches to the -/// entry block of a function). Because the block can have no predecessors, it -/// also cannot have any PHI nodes. +/// Creating a Basic Block +/// ====================== +/// +/// By default, the initializer for a basic block merely creates the block but +/// does not associate it with a function. +/// +/// let module = Module(name: "Example") +/// let fun = builder.addFunction("example", +/// type: FunctionType([], VoidType())) +/// +/// // This basic block is "floating" outside of a function. +/// let floatingBB = BasicBlock(name: "floating") +/// // Until we associate it with a function by calling `Function.append(_:)`. +/// fun.append(floatingBB) +/// +/// A basic block may be created and automatically inserted at the end of a +/// function by calling `Function.appendBasicBlock(named:in:)`. +/// +/// let module = Module(name: "Example") +/// let fun = builder.addFunction("example", +/// type: FunctionType([], VoidType())) +/// +/// // This basic block is "attached" to the example function. +/// let attachedBB = fun.appendBasicBlock(named: "attached") +/// +/// The Address of a Basic Block +/// ============================ +/// +/// Basic blocks (except the entry block) may have their labels appear in the +/// symbol table. Naturally, these labels are associated with address values +/// in the final object file. The value of that address may be accessed for the +/// purpose of an indirect call or a direct comparisson by calling +/// `Function.address(of:)` and providing one of the function's child blocks as +/// an argument. Providing any other basic block outside of the function as an +/// argument value is undefined. +/// +/// The Entry Block +/// =============== +/// +/// The first basic block (the entry block) in a `Function` is special: +/// +/// - The entry block is immediately executed when the flow of control enters +/// its parent function. +/// - The entry block is not allowed to have predecessor basic blocks +/// (i.e. there cannot be any branches to the entry block of a function). +/// - The address of the entry block is not a well-defined value. +/// - The entry block cannot have PHI nodes. This is enforced structurally, +/// as the entry block can have no predecessor blocks to serve as operands +/// to the PHI node. +/// - Static `alloca` instructions situated in the entry block are treated +/// specially by most LLVM backends. For example, FastISel keeps track of +/// static `alloca` values in the entry block to more efficiently reference +/// them from the base pointer of the stack frame. public struct BasicBlock: IRValue { internal let llvm: LLVMBasicBlockRef @@ -23,19 +77,51 @@ public struct BasicBlock: IRValue { self.llvm = llvm } + /// Creates a new basic block without a parent function. + /// + /// The basic block should be inserted into a function or destroyed before + /// the IR builder is finalized. + public init(context: Context = .global, name: String = "") { + self.llvm = LLVMCreateBasicBlockInContext(context.llvm, name) + } + + /// Given that this block and a given block share a parent function, move this + /// block before the given block in that function's basic block list. + /// + /// - Parameter position: The basic block that acts as a position before + /// which this block will be moved. + public func move(before position: BasicBlock) { + LLVMMoveBasicBlockBefore(self.asLLVM(), position.asLLVM()) + } + + /// Given that this block and a given block share a parent function, move this + /// block after the given block in that function's basic block list. + /// + /// - Parameter position: The basic block that acts as a position after + /// which this block will be moved. + public func move(after position: BasicBlock) { + LLVMMoveBasicBlockAfter(self.asLLVM(), position.asLLVM()) + } + /// Retrieves the underlying LLVM value object. public func asLLVM() -> LLVMValueRef { return llvm } + /// Retrieves the name of this basic block. + public var name: String { + let cstring = LLVMGetBasicBlockName(self.llvm) + return String(cString: cstring!) + } + /// Returns the first instruction in the basic block, if it exists. - public var firstInstruction: Instruction? { + public var firstInstruction: IRInstruction? { guard let val = LLVMGetFirstInstruction(llvm) else { return nil } return Instruction(llvm: val) } /// Returns the first instruction in the basic block, if it exists. - public var lastInstruction: Instruction? { + public var lastInstruction: IRInstruction? { guard let val = LLVMGetLastInstruction(llvm) else { return nil } return Instruction(llvm: val) } @@ -66,10 +152,10 @@ public struct BasicBlock: IRValue { } /// Returns a sequence of the Instructions that make up this basic block. - public var instructions: AnySequence { + public var instructions: AnySequence { var current = firstInstruction - return AnySequence { - return AnyIterator { + return AnySequence { + return AnyIterator { defer { current = current?.next() } return current } @@ -96,18 +182,6 @@ public struct BasicBlock: IRValue { } } -extension BasicBlock { - /// Deletes the basic block from its containing function. - /// - note: This does not remove breaks to this block from the - /// function. Ensure you have removed all instructions that reference - /// this basic block before deleting it. - @available(*, deprecated, message: "it is hard to use correctly and will be removed. See BasicBlock.removeFromParent() instead") - public func delete() { - LLVMDeleteBasicBlock(llvm) - } - -} - extension BasicBlock { /// An `Address` represents a function-relative address of a basic block for /// use with the `indirectbr` instruction. @@ -124,3 +198,9 @@ extension BasicBlock { } } } + +extension BasicBlock: Equatable { + public static func == (lhs: BasicBlock, rhs: BasicBlock) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() + } +} diff --git a/Sources/LLVM/Call.swift b/Sources/LLVM/Call.swift index f8a51a42..459c22c8 100644 --- a/Sources/LLVM/Call.swift +++ b/Sources/LLVM/Call.swift @@ -1,9 +1,10 @@ #if SWIFT_PACKAGE import cllvm +import llvmshims #endif /// Represents a simple function call. -public struct Call: IRValue { +public struct Call: IRInstruction { let llvm: LLVMValueRef /// Retrieves the underlying LLVM value object. @@ -18,12 +19,14 @@ public struct Call: IRValue { /// Accesses the calling convention for this function call. public var callingConvention: CallingConvention { - get { return CallingConvention(rawValue: LLVMGetInstructionCallConv(self.llvm))! } - set { LLVMSetInstructionCallConv(self.llvm, newValue.rawValue) } + get { return CallingConvention(llvm: LLVMCallConv(rawValue: LLVMGetInstructionCallConv(self.llvm))) } + set { LLVMSetInstructionCallConv(self.llvm, newValue.llvm.rawValue) } } - /// Returns whether this function call is a tail call. That is, if the callee - /// may reuse the stack memory of the caller. + /// Returns whether this function call is a tail call. + /// + /// A tail call may not reference memory in the stack frame of the calling + /// function. Therefore, the callee may reuse the stack memory of the caller. /// /// This attribute requires support from the target architecture. public var isTailCall: Bool { @@ -31,19 +34,35 @@ public struct Call: IRValue { set { LLVMSetTailCall(self.llvm, newValue.llvm) } } + /// Accesses the tail call marker associated with this call. + /// + /// The presence of the tail call marker affects the optimizer's decisions + /// around tail call optimizations. The presence of a `tail` or `mustTail` + /// marker, either inserted by the user or by the optimizer, is a strong + /// hint (or a requirement) that tail call optimizations occur. The presence + /// of `noTail` acts to block any tail call optimization. + /// + /// Tail call optimization is finicky and requires a number of complex + /// invariants hold before a call is eligible for the optimization. + /// Even then, it is not necessarily guaranteed by LLVM in all cases. + public var tailCallKind: TailCallKind { + get { return TailCallKind(llvm: LLVMGetTailCallKind(self.llvm)) } + set { return LLVMSetTailCallKind(self.llvm, newValue.llvm) } + } + /// Retrieves the alignment of the parameter at the given index. /// /// This property is currently set-only due to limitations of the LLVM C API. /// /// - parameter i: The index of the parameter to retrieve. /// - parameter alignment: The alignment to apply to the parameter. - public func setParameterAlignment(at i : Int, to alignment: Int) { - LLVMSetInstrParamAlignment(self.llvm, UInt32(i), UInt32(alignment)) + public func setParameterAlignment(at i : Int, to alignment: Alignment) { + LLVMSetInstrParamAlignment(self.llvm, UInt32(i), alignment.rawValue) } } /// Represents a function call that may transfer control to an exception handler. -public struct Invoke: IRValue { +public struct Invoke: IRInstruction { let llvm: LLVMValueRef /// Retrieves the underlying LLVM value object. @@ -64,3 +83,84 @@ public struct Invoke: IRValue { set { LLVMSetUnwindDest(self.llvm, newValue.asLLVM()) } } } + +extension Call { + /// Optimization markers for tail call elimination. + public enum TailCallKind { + /// No optimization tail call marker is present. The optimizer is free to + /// infer one of the other tail call markers. + case none + /// Suggests that tail call optimization should be performed on this + /// function. Note that this is not a guarantee. + /// + /// `tail` calls may not access caller-provided allocas, and may not + /// access varargs. + /// + /// Tail call optimization for calls marked tail is guaranteed to occur if + /// the following conditions are met: + /// + /// - Caller and callee both have the calling convention `fastcc`. + /// - The call is in tail position (ret immediately follows `call` and + /// `ret` uses value of call or is void). + /// - Tail call elimination is enabled in the target machine's + /// `TargetOptions` or is globally enabled in LLVM. + /// - Platform-specific constraints are met. + case tail + /// Requires the tail call optimization be performed in order for this call + /// to proceed correctly. + /// + /// Tail calls guarantee the following invariants: + /// + /// - The call will not cause unbounded stack growth if it is part of a + /// recursive cycle in the call graph. + /// - Arguments with the `inalloca` attribute are forwarded in place. + /// - If the musttail call appears in a function with the `thunk` + /// attribute and the caller and callee both have varargs, than any + /// unprototyped arguments in register or memory are forwarded to the + /// callee. Similarly, the return value of the callee is returned the + /// the caller’s caller, even if a `void` return type is in use. + /// + /// `mustTail` calls may not access caller-provided allocas, and may not + /// access varargs. Unlike `tail`s, they are also subject to the following + /// restrictions: + /// + /// - The call must immediately precede a `ret` instruction, or a pointer + /// `bitcast` followed by a `ret` instruction. + /// - The `ret` instruction must return the (possibly `bitcast`ed) value + /// produced by the `call`, or return `void`. + /// - The caller and callee prototypes must match. Pointer types of + /// parameters or return types may differ in pointee type, but not in + /// address space. + /// - The calling conventions of the caller and callee must match. + /// - All ABI-impacting function attributes, such as `sret`, `byval`, + /// `inreg`, `returned`, and `inalloca`, must match. + /// - The callee must be varargs iff the caller is varargs. Bitcasting a + /// non-varargs function to the appropriate varargs type is legal so + /// long as the non-varargs prefixes obey the other rules. + case mustTail + /// Prevents tail call optimizations from being performed or inferred. + case noTail + + internal init(llvm: LLVMTailCallKind) { + switch llvm { + case LLVMTailCallKindNone: self = .none + case LLVMTailCallKindTail: self = .tail + case LLVMTailCallKindMustTail: self = .mustTail + case LLVMTailCallKindNoTail: self = .noTail + default: fatalError("unknown tail call kind \(llvm)") + } + } + + private static let tailCallKindMapping: [TailCallKind: LLVMTailCallKind] = [ + .none: LLVMTailCallKindNone, + .tail: LLVMTailCallKindTail, + .mustTail: LLVMTailCallKindMustTail, + .noTail: LLVMTailCallKindNoTail, + ] + + /// Retrieves the corresponding `LLVMTailCallKind`. + public var llvm: LLVMTailCallKind { + return TailCallKind.tailCallKindMapping[self]! + } + } +} diff --git a/Sources/LLVM/CallingConvention.swift b/Sources/LLVM/CallingConvention.swift new file mode 100644 index 00000000..0643b1ac --- /dev/null +++ b/Sources/LLVM/CallingConvention.swift @@ -0,0 +1,426 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +/// Enumerates the calling conventions supported by LLVM. +public enum CallingConvention { + /// The default LLVM calling convention, compatible with C. + case c + /// This calling convention attempts to make calls as fast as possible + /// (e.g. by passing things in registers). This calling convention + /// allows the target to use whatever tricks it wants to produce fast + /// code for the target, without having to conform to an externally + /// specified ABI (Application Binary Interface). `Tail calls can only + /// be optimized when this, the `ghc` or the `hiPE` convention is + /// used. This calling convention does not support varargs and requires the + /// prototype of all callees to exactly match the prototype of the function + /// definition. + case fast + /// This calling convention attempts to make code in the caller as + /// efficient as possible under the assumption that the call is not + /// commonly executed. As such, these calls often preserve all registers + /// so that the call does not break any live ranges in the caller side. + /// This calling convention does not support varargs and requires the + /// prototype of all callees to exactly match the prototype of the + /// function definition. Furthermore the inliner doesn't consider such + /// function calls for inlining. + case cold + /// This calling convention has been implemented specifically for use by + /// the Glasgow Haskell Compiler (GHC). + /// + /// It passes everything in registers, going to extremes to achieve this + /// by disabling callee save registers. This calling convention should + /// not be used lightly but only for specific situations such as an + /// alternative to the *register pinning* performance technique often + /// used when implementing functional programming languages. At the + /// moment only X86 supports this convention and it has the following + /// limitations: + /// + /// - On *X86-32* only supports up to 4 bit type parameters. No + /// floating-point types are supported. + /// - On *X86-64* only supports up to 10 bit type parameters and 6 + /// floating-point parameters. + /// + /// This calling convention supports `tail call + /// optimization but requires both the caller and callee are using it. + case ghc + /// This calling convention has been implemented specifically for use by + /// the High-Performance Erlang (HiPE) compiler, *the* + /// native code compiler of the `Ericsson's Open Source Erlang/OTP + /// system. + /// + /// It uses more registers for argument passing than the ordinary C calling + /// convention and defines no callee-saved registers. The calling + /// convention properly supports tail call optimization but requires that + /// both the caller and the callee use it. + /// + /// It uses a *register pinning* mechanism, similar to GHC's convention, for + /// keeping frequently accessed runtime components pinned to specific hardware + /// registers. + /// + /// At the moment only X86 supports this convention (both 32 and 64 bit). + case hiPE + /// This calling convention has been implemented for WebKit FTL JIT. It passes + /// arguments on the stack right to left (as cdecl does), and returns a value + /// in the platform's customary return register. + case webKitJS + /// Calling convention for dynamic register based calls + /// (e.g. stackmap and patchpoint intrinsics). + /// + /// This is a special convention that supports patching an arbitrary code + /// sequence in place of a call site. This convention forces the call + /// arguments into registers but allows them to be dynamically + /// allocated. This can currently only be used with calls to + /// `llvm.experimental.patchpoint` because only this intrinsic records + /// the location of its arguments in a side table. + case anyReg + /// Calling convention for runtime calls that preserves most registers. + /// + /// This calling convention attempts to make the code in the caller as + /// unintrusive as possible. This convention behaves identically to the `c` + /// calling convention on how arguments and return values are passed, but it + /// uses a different set of caller/callee-saved registers. This alleviates the + /// burden of saving and recovering a large register set before and after the + /// call in the caller. If the arguments are passed in callee-saved registers, + /// then they will be preserved by the callee across the call. This doesn't + /// apply for values returned in callee-saved registers. + /// + /// On X86-64 the callee preserves all general purpose registers, except for + /// R11. R11 can be used as a scratch register. Floating-point registers + /// (XMMs/YMMs) are not preserved and need to be saved by the caller. + /// + /// The idea behind this convention is to support calls to runtime functions + /// that have a hot path and a cold path. The hot path is usually a small + /// piece of code that doesn't use many registers. The cold path might need to + /// call out to another function and therefore only needs to preserve the + /// caller-saved registers, which haven't already been saved by the caller. + /// + /// The `preserveMost` calling convention is very similar to the `cold` + /// calling convention in terms of caller/callee-saved registers, but they are + /// used for different types of function calls. `cold` is for function calls + /// that are rarely executed, whereas `preserveMost` function calls are + /// intended to be on the hot path and definitely executed a lot. Furthermore + /// `preserveMost` doesn't prevent the inliner from inlining the function + /// call. + /// + /// This calling convention will be used by a future version of the + /// Objective-C runtime and should therefore still be considered experimental + /// at this time. + /// + /// Although this convention was created to optimize certain runtime calls to + /// the ObjectiveC runtime, it is not limited to this runtime and might be + /// used by other runtimes in the future too. + /// + /// The current implementation only supports X86-64, but the intention is to + /// support more architectures in the future. + case preserveMost + /// This calling convention attempts to make the code in the caller even less + /// intrusive than the `preserveMost` calling convention. This calling + /// convention also behaves identical to the `c` calling convention on how + /// arguments and return values are passed, but it uses a different set of + /// caller/callee-saved registers. This removes the burden of saving and + /// recovering a large register set before and after the call in the caller. + /// + /// If the arguments are passed in callee-saved registers, then they will be + /// preserved by the callee across the call. This doesn't apply for values + /// returned in callee-saved registers. + /// + /// - On X86-64 the callee preserves all general purpose registers, except for + /// R11. R11 can be used as a scratch register. Furthermore it also preserves + /// all floating-point registers (XMMs/YMMs). + /// + /// The idea behind this convention is to support calls to runtime functions + /// that don't need to call out to any other functions. + /// + /// This calling convention, like the `preserveMost` calling convention, + /// will be used by a future version of the ObjectiveC runtime and should be + /// considered experimental at this time. + case preserveAll + /// Calling convention for Swift. + /// + /// - On X86-64 `RCX` and `R8` are available for additional integer returns, + /// and `XMM2` and `XMM3` are available for additional FP/vector returns. + /// - On iOS platforms, we use the `armAAPCSVFP` calling convention. + case swift + /// The calling convention for accessors to C++-style thread-local storage. + /// + /// The access function generally has an entry block, an exit block + /// and an initialization block that is run at the first time. The entry and + /// exit blocks can access a few TLS IR variables, each access will be lowered + /// to a platform-specific sequence. + /// + /// This calling convention aims to minimize overhead in the caller by + /// preserving as many registers as possible (all the registers that are + /// perserved on the fast path, composed of the entry and exit blocks). + /// + /// This calling convention behaves identical to the `C` calling convention on + /// how arguments and return values are passed, but it uses a different set of + /// caller/callee-saved registers. + /// + /// Given that each platform has its own lowering sequence, hence its own set + /// of preserved registers, we can't use the existing `preserveMost`. + /// + /// - On X86-64 the callee preserves all general purpose registers, except for + /// RDI and RAX. + case cxxFastThreadLocalStorage + /// The calling conventions mostly used by the Win32 API. + /// + /// It is basically the same as the C convention with the difference in that + /// the callee is responsible for popping the arguments from the stack. + case x86StandardCall + /// "Fast" analog of `x86Stdcall`. + /// + /// Passes first two arguments in ECX:EDX registers, others via the stack. + /// The callee is responsible for stack cleaning. + case x86FastCall + /// Short for "ARM Procedure Calling Standard" calling convention (obsolete, + /// but still used on some targets). + case armAPCS + /// Short for "ARM Architecture Procedure Calling Standard" calling + /// convention. This is often referred to as EABI - though this terminology + /// can be confusing for those that remember EABI from PowerPC. + /// + /// `armAAPCS` is the modern incarnation of `armAPCS`. It enables a number of + /// desirable optimizations over `armAPCS` such as tighter packing of + /// structures and (emulated) floating point instructions. `armAPCS` suffered + /// a 10x performance penalty in environments without a floating point + /// co-processor, as floating routines would be implemented by trapping to + /// software implementations in the kernel. + case armAAPCS + /// Same as `armAAPCS`, but uses hardware floating point ABI. On + /// ARM architectures before ARMv8, these instructions are implemented as + /// co-processor extensions. + /// + /// Despite `VFP` being short for "Vector Floating Point", processing of data + /// is entirely sequential. VFP does not perform actual vector computing + /// in the usual sense (SIMD), and is generally replaced by NEON intrinsics. + case armAAPCSVFP + /// Calling convention used for MSP430 interrupt service routines (ISRs). + /// + /// ISRs may not accept or return arguments in registers. They should ideally + /// save all registers when they are first invoked and must clean up before + /// returning with the special `RETI` instruction. LLVM will trap if any of + /// these invariants are violated. + case msp430Interrupt + /// Similar to `x86Stdcall`. + /// + /// - On x86_64 it passes the first argument (a pointer to `this` in C++) in + /// `ECX` and the others via the stack from right to left. The callee is + /// responsible for popping the arguments from the stack. + /// + /// MSVC uses this by default for methods in its ABI for all non-variadic + /// member method calls. + case x86ThisCall + /// Calling convention for Parallel Thread Execution (PTX) kernel functions. + /// + /// In PTX, there are two types of functions: device functions, which are only + /// callable by device code, and kernel functions, which are callable by host + /// code. Use this calling convention for kernel functions. + /// + /// The parameter (`.param`) state space is used to pass input arguments + /// from the host to the kernel, to declare formal input and return + /// parameters for device functions called from within kernel execution, and + /// to declare locally-scoped byte array variables that serve as function + /// call arguments, typically for passing large structures by value to a + /// function. + /// + /// Kernel function parameters differ from device function parameters in terms + /// of access and sharing (read-only versus read-write, per-kernel versus + /// per-thread). + case ptxKernelFunction + /// Calling convention for Parallel Thread Execution (PTX) device functions. + /// + /// Passes all arguments in register or parameter space. + /// + /// Registers (.reg state space) are fast storage locations. The number of + /// registers is limited, and will vary from platform to platform. When the + /// limit is exceeded, register variables will be spilled to memory, causing + /// changes in performance. + /// + /// Device function parameters differ from kernel function parameters in that + /// they may not necessarily be directly addressable. Because the exact + /// location of argument values is implementation-defined, requesting the + /// address of a device argument is generally not supported. + case ptxDeviceFunction + /// Calling convention for SPIR non-kernel device functions. + /// + /// No lowering or expansion of arguments. + /// Structures are passed as a pointer to a struct with the byval attribute. + /// Functions can only call SPIR_FUNC and SPIR_KERNEL functions. + /// Functions can only have zero or one return values. + /// Variable arguments are not allowed, except for printf. + /// How arguments/return values are lowered are not specified. + /// Functions are only visible to the devices. + case spirDeviceFunction + /// Calling convention for SPIR kernel functions. + /// + /// Inherits the restrictions of `.spirFunction`, except + /// Cannot have non-void return values. + /// Cannot have variable arguments. + /// Can also be called by the host. + /// Is externally visible. + case spirKernelFunction + /// Calling conventions for Intel OpenCL built-ins. + /// + /// Extends the x86_32 C ABI for passing and returning values by a set of + /// high-bitwidth registers for passing arguments and returning values from + /// functions, and a set of mask registers. + case intelOpenCLBuiltin + /// The C convention as specified in the x86-64 supplement to the + /// System V ABI, used on most non-Windows systems. + case x8664SystemV + /// The C convention as implemented on Windows/x86-64 and + /// AArch64. This convention differs from the more common + /// `x8664SystemV` convention in a number of ways, most notably in + /// that XMM registers used to pass arguments are shadowed by GPRs, + /// and vice versa. + /// + /// On AArch64, this is identical to the normal C (`aapcs`) calling + /// convention for normal functions, but floats are passed in integer + /// registers to variadic functions. + case win64 + /// MSVC calling convention that passes vectors and vector aggregates + /// in SSE registers. + case x86VectorCall + /// Calling convention used by HipHop Virtual Machine (HHVM) to + /// perform calls to and from translation cache, and for calling PHP + /// functions. + /// + /// HHVM is a very relaxed convention that marks as many registers as + /// general-purpose as possible, including RBP which contains the first + /// argument, but excluding RSP and R12 which are used for the stack pointer + /// and return value respectively. + /// + /// This calling convention supports tail and sibling call elimination. + case hhvm + /// HHVM calling convention for invoking C/C++ helpers. + /// + /// This calling convention differs from the standard `c` calling convention + /// in that the first argument is passed in RBP. + case hhvmc + /// The calling convention for x86 hardware interrupts. + /// + /// The callee may take one or two parameters, where the 1st represents a + /// pointer to hardware context frame and the 2nd represents a hardware error + /// code. The presence of the latter depends on the interrupt vector taken. + /// + /// This convention is valid for both 32-bit and 64-bit subtargets. + case x86Interrupt + /// Calling convention for AVR interrupt routines. + case avrInterrupt + /// Calling convention used for AVR signal routines. + case avrSignal + /// Calling convention used for special AVR rtlib functions + /// which have an "optimized" convention to preserve registers. + case avrBuiltin + /// Calling convention used for Mesa vertex shaders, or AMDPAL last shader + /// stage before rasterization (vertex shader if tessellation and geometry + /// are not in use, or otherwise copy shader if one is needed). + case amdGPUVertexShader + /// Calling convention used for Mesa/AMDPAL geometry shaders. + case amdGPUGeometryShader + /// Calling convention used for Mesa/AMDPAL pixel shaders. + case amdGPUPixelShader + /// Calling convention used for Mesa/AMDPAL compute shaders. + case amdGPUComputeShader + /// Calling convention for AMDGPU code object kernels. + case amdGPUKernel + /// Register calling convention used for parameters transfer optimization + case x86RegisterCall + /// Calling convention used for Mesa/AMDPAL hull shaders (= tessellation + /// control shaders). + case amdGPUHullShader + /// Calling convention used for special MSP430 rtlib functions + /// which have an "optimized" convention using additional registers. + case msp430Builtin + /// Calling convention used for AMDPAL vertex shader if tessellation is in + /// use. + case amdGPULS + /// Calling convention used for AMDPAL shader stage before geometry shader + /// if geometry is in use. So either the domain (= tessellation evaluation) + /// shader if tessellation is in use, or otherwise the vertex shader. + case amdGPUES + + internal init(llvm: LLVMCallConv) { + switch llvm { + case LLVMCCallConv: self = .c + case LLVMFastCallConv: self = .fast + case LLVMColdCallConv: self = .cold + case LLVMGHCCallConv: self = .ghc + case LLVMHiPECallConv: self = .hiPE + case LLVMWebKitJSCallConv: self = .webKitJS + case LLVMAnyRegCallConv: self = .anyReg + case LLVMPreserveMostCallConv: self = .preserveMost + case LLVMPreserveAllCallConv: self = .preserveAll + case LLVMSwiftCallConv: self = .swift + case LLVMCXXFASTTLSCallConv: self = .cxxFastThreadLocalStorage + case LLVMX86StdcallCallConv: self = .x86StandardCall + case LLVMX86FastcallCallConv: self = .x86FastCall + case LLVMARMAPCSCallConv: self = .armAPCS + case LLVMARMAAPCSCallConv: self = .armAAPCS + case LLVMARMAAPCSVFPCallConv: self = .armAAPCSVFP + case LLVMMSP430INTRCallConv: self = .msp430Interrupt + case LLVMX86ThisCallCallConv: self = .x86ThisCall + case LLVMPTXKernelCallConv: self = .ptxKernelFunction + case LLVMPTXDeviceCallConv: self = .ptxDeviceFunction + case LLVMSPIRFUNCCallConv: self = .spirDeviceFunction + case LLVMSPIRKERNELCallConv: self = .spirKernelFunction + case LLVMIntelOCLBICallConv: self = .intelOpenCLBuiltin + case LLVMX8664SysVCallConv: self = .x8664SystemV + case LLVMWin64CallConv: self = .win64 + case LLVMX86VectorCallCallConv: self = .x86VectorCall + case LLVMHHVMCallConv: self = .hhvm + case LLVMHHVMCCallConv: self = .hhvmc + case LLVMX86INTRCallConv: self = .x86Interrupt + case LLVMAVRINTRCallConv: self = .avrInterrupt + case LLVMAVRSIGNALCallConv: self = .avrSignal + case LLVMAVRBUILTINCallConv: self = .avrBuiltin + case LLVMAMDGPUVSCallConv: self = .amdGPUVertexShader + case LLVMAMDGPUGSCallConv: self = .amdGPUGeometryShader + case LLVMAMDGPUPSCallConv: self = .amdGPUPixelShader + case LLVMAMDGPUCSCallConv: self = .amdGPUComputeShader + case LLVMAMDGPUKERNELCallConv: self = .amdGPUKernel + case LLVMX86RegCallCallConv: self = .x86RegisterCall + case LLVMAMDGPUHSCallConv: self = .amdGPUHullShader + case LLVMMSP430BUILTINCallConv: self = .msp430Builtin + case LLVMAMDGPULSCallConv: self = .amdGPULS + case LLVMAMDGPUESCallConv: self = .amdGPUES + default: fatalError("unknown calling convention \(llvm)") + } + } + + private static let conventionMapping: [CallingConvention: LLVMCallConv] = [ + .c : LLVMCCallConv, .fast : LLVMFastCallConv, .cold : LLVMColdCallConv, + .ghc : LLVMGHCCallConv, .hiPE : LLVMHiPECallConv, + .webKitJS : LLVMWebKitJSCallConv, .anyReg : LLVMAnyRegCallConv, + .preserveMost : LLVMPreserveMostCallConv, + .preserveAll : LLVMPreserveAllCallConv, .swift : LLVMSwiftCallConv, + .cxxFastThreadLocalStorage : LLVMCXXFASTTLSCallConv, + .x86StandardCall : LLVMX86StdcallCallConv, + .x86FastCall : LLVMX86FastcallCallConv, .armAPCS : LLVMARMAPCSCallConv, + .armAAPCS : LLVMARMAAPCSCallConv, .armAAPCSVFP : LLVMARMAAPCSVFPCallConv, + .msp430Interrupt : LLVMMSP430INTRCallConv, + .x86ThisCall : LLVMX86ThisCallCallConv, .ptxKernelFunction : LLVMPTXKernelCallConv, + .ptxDeviceFunction : LLVMPTXDeviceCallConv, .spirDeviceFunction : LLVMSPIRFUNCCallConv, + .spirKernelFunction : LLVMSPIRKERNELCallConv, .intelOpenCLBuiltin : LLVMIntelOCLBICallConv, + .x8664SystemV : LLVMX8664SysVCallConv, .win64 : LLVMWin64CallConv, + .x86VectorCall : LLVMX86VectorCallCallConv, .hhvm : LLVMHHVMCallConv, + .hhvmc : LLVMHHVMCCallConv, .x86Interrupt : LLVMX86INTRCallConv, + .avrInterrupt : LLVMAVRINTRCallConv, .avrSignal : LLVMAVRSIGNALCallConv, + .avrBuiltin : LLVMAVRBUILTINCallConv, + .amdGPUVertexShader : LLVMAMDGPUVSCallConv, + .amdGPUGeometryShader : LLVMAMDGPUGSCallConv, + .amdGPUPixelShader : LLVMAMDGPUPSCallConv, + .amdGPUComputeShader : LLVMAMDGPUCSCallConv, + .amdGPUKernel : LLVMAMDGPUKERNELCallConv, + .x86RegisterCall : LLVMX86RegCallCallConv, + .amdGPUHullShader : LLVMAMDGPUHSCallConv, + .msp430Builtin : LLVMMSP430BUILTINCallConv, + .amdGPULS : LLVMAMDGPULSCallConv, .amdGPUES : LLVMAMDGPUESCallConv, + ] + + /// Retrieves the corresponding `LLVMCallConv`. + public var llvm: LLVMCallConv { + return CallingConvention.conventionMapping[self]! + } +} diff --git a/Sources/LLVM/Comdat.swift b/Sources/LLVM/Comdat.swift new file mode 100644 index 00000000..2d542755 --- /dev/null +++ b/Sources/LLVM/Comdat.swift @@ -0,0 +1,124 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +/// A `Comdat` object represents a particular COMDAT section in a final +/// generated ELF or COFF object file. All COMDAT sections are keyed by a +/// unique name that the linker uses, in conjunction with the section's +/// `selectionKind` to determine how to treat conflicting or identical COMDAT +/// sections at link time. +/// +/// COMDAT sections are typically used by languages where multiple translation +/// units may define the same symbol, but where +/// "One-Definition-Rule" (ODR)-like concepts apply (perhaps because taking the +/// address of the object referenced by the symbol is defined behavior). For +/// example, a C++ header file may define an inline function that cannot be +/// successfully inlined at all call sites. The C++ compiler would then emit +/// a COMDAT section in each object file for the function with the `.any` +/// selection kind and the linker would pick any section it desires before +/// emitting the final object file. +/// +/// It is important to be aware of the selection kind of a COMDAT section as +/// these provide strengths and weaknesses at compile-time and link-time. It +/// is also important to be aware that only certain platforms support mixing +/// identically-keyed COMDAT sections with mixed selection kinds e.g. COFF +/// supports mixing `.any` and `.largest`, WebAssembly only supports `.any`, +/// and Mach-O doesn't support COMDAT sections at all. +/// +/// When targeting COFF, there are also restrictions on the way global objects +/// must appear in COMDAT sections. All global objects and aliases to those +/// global objects must belong to a COMDAT group with the same name and must +/// have greater than local linkage. Else the local symbol may be renamed in +/// the event of a collision, defeating code-size savings. +/// +/// The combined use of COMDATS and sections may yield surprising results. +/// For example: +/// +/// let module = Module(name: "COMDATTest") +/// let builder = IRBuilder(module: module) +/// +/// let foo = module.comdat(named: "foo") +/// let bar = module.comdat(named: "bar") +/// +/// var g1 = builder.addGlobal("g1", initializer: IntType.int8.constant(42)) +/// g1.comdat = foo +/// var g2 = builder.addGlobal("g2", initializer: IntType.int8.constant(42)) +/// g2.comdat = bar +/// +/// From the object file perspective, this requires the creation of two sections +/// with the same name. This is necessary because both globals belong to +/// different COMDAT groups and COMDATs, at the object file level, are +/// represented by sections. +public class Comdat { + internal let llvm: LLVMComdatRef + + internal init(llvm: LLVMComdatRef) { + self.llvm = llvm + } + + /// The selection kind for this COMDAT section. + public var selectionKind: Comdat.SelectionKind { + get { return Comdat.SelectionKind(llvm: LLVMGetComdatSelectionKind(self.llvm)) } + set { LLVMSetComdatSelectionKind(self.llvm, newValue.llvm) } + } +} + +extension Comdat { + /// A `Comdat.SelectionKind` describes the behavior of the linker when + /// linking COMDAT sections. + public enum SelectionKind { + /// The linker may choose any COMDAT section with a matching key. + /// + /// This selection kind is the most relaxed - any section with the same key + /// but not necessarily identical size or contents can be chosen. Precisely + /// which section is chosen is implementation-defined. + /// + /// This selection kind is the default for all newly-inserted sections. + case any + /// The linker may choose any identically-keyed COMDAT section and requires + /// all other referenced data to match its selection's referenced data. + /// + /// This selection kind requires that the data in each COMDAT section be + /// identical in length and content. Inclusion of multiple non-identical + /// COMDAT sections with the same key is an error. + /// + /// For global objects in LLVM, identical contents is defined to mean that + /// their initializers point to the same global `IRValue`. + case exactMatch + /// The linker chooses the identically-keyed COMDAT section with the largest + /// size, ignoring content. + case largest + /// The COMDAT section with this key is unique. + /// + /// This selection requires that no other COMDAT section have the same key + /// as this section, making the choice of selection unambiguous. Inclusion + /// of any other COMDAT section with the same key is an error. + case noDuplicates + /// The linker may choose any identically-keyed COMDAT section and requires + /// all other sections to have the same size as its selection. + case sameSize + + internal init(llvm: LLVMComdatSelectionKind) { + switch llvm { + case LLVMAnyComdatSelectionKind: self = .any + case LLVMExactMatchComdatSelectionKind: self = .exactMatch + case LLVMLargestComdatSelectionKind: self = .largest + case LLVMNoDuplicatesComdatSelectionKind: self = .noDuplicates + case LLVMSameSizeComdatSelectionKind: self = .sameSize + default: fatalError("unknown comdat selection kind \(llvm)") + } + } + + private static let comdatMapping: [Comdat.SelectionKind: LLVMComdatSelectionKind] = [ + .any: LLVMAnyComdatSelectionKind, + .exactMatch: LLVMExactMatchComdatSelectionKind, + .largest: LLVMLargestComdatSelectionKind, + .noDuplicates: LLVMNoDuplicatesComdatSelectionKind, + .sameSize: LLVMSameSizeComdatSelectionKind, + ] + + fileprivate var llvm: LLVMComdatSelectionKind { + return SelectionKind.comdatMapping[self]! + } + } +} diff --git a/Sources/LLVM/Constant.swift b/Sources/LLVM/Constant.swift index d041e6c9..811c761e 100644 --- a/Sources/LLVM/Constant.swift +++ b/Sources/LLVM/Constant.swift @@ -2,6 +2,38 @@ import cllvm #endif +/// An `IRConstant` is an entity whose value doees not change during the +/// runtime of a program. This includes global variables and functions, whose +/// addresses are constant, and constant expressions. +public protocol IRConstant: IRValue {} + +extension IRConstant { + /// Perform a GEP (Get Element Pointer) with this value as the base. + /// + /// - parameter indices: A list of indices that indicate which of the elements + /// of the aggregate object are indexed. + /// + /// - returns: A value representing the address of a subelement of the given + /// aggregate data structure value. + public func constGEP(indices: [IRConstant]) -> IRConstant { + var idxs = indices.map { $0.asLLVM() as Optional } + return idxs.withUnsafeMutableBufferPointer { buf in + return Constant(llvm: LLVMConstGEP(asLLVM(), buf.baseAddress, UInt32(buf.count))) + } + } + + /// Build a constant bitcast to convert the given value to a value of the + /// given type by just copying the bit pattern. + /// + /// - parameter type: The destination type. + /// + /// - returns: A constant value representing the result of bitcasting this + /// constant value to fit the given type. + public func bitCast(to type: IRType) -> IRConstant { + return Constant(llvm: LLVMConstBitCast(asLLVM(), type.asLLVM())) + } +} + /// A protocol to which the phantom types for a constant's representation conform. public protocol ConstantRepresentation {} /// A protocol to which the phantom types for all numerical constants conform. @@ -29,7 +61,7 @@ public enum Vector: ConstantRepresentation {} /// `Constant`s keep track of the values they represent at the type level to /// disallow mixed-type arithmetic. Use the `cast` family of operations to /// safely convert constants to other representations. -public struct Constant: IRValue { +public struct Constant: IRConstant { internal let llvm: LLVMValueRef internal init(llvm: LLVMValueRef!) { @@ -165,7 +197,53 @@ extension Constant where Repr == Struct { } } +// MARK: Truncation +extension Constant where Repr == Signed { + /// Creates a constant truncated to a given integral type. + /// + /// - parameter type: The type to truncate towards. + /// + /// - returns: A const value representing this value truncated to the given + /// integral type's bitwidth. + public func truncate(to type: IntType) -> Constant { + return Constant(llvm: LLVMConstTrunc(llvm, type.asLLVM())) + } +} + +extension Constant where Repr == Unsigned { + /// Creates a constant truncated to a given integral type. + /// + /// - parameter type: The type to truncate towards. + /// + /// - returns: A const value representing this value truncated to the given + /// integral type's bitwidth. + public func truncate(to type: IntType) -> Constant { + return Constant(llvm: LLVMConstTrunc(llvm, type.asLLVM())) + } +} + +extension Constant where Repr == Floating { + /// Creates a constant truncated to a given floating type. + /// + /// - parameter type: The type to truncate towards. + /// + /// - returns: A const value representing this value truncated to the given + /// floating type's bitwidth. + public func truncate(to type: FloatType) -> Constant { + return Constant(llvm: LLVMConstFPTrunc(llvm, type.asLLVM())) + } + + /// Creates a constant extended to a given floating type. + /// + /// - parameter type: The type to extend towards. + /// + /// - returns: A const value representing this value extended to the given + /// floating type's bitwidth. + public func extend(to type: FloatType) -> Constant { + return Constant(llvm: LLVMConstFPExt(llvm, type.asLLVM())) + } +} // MARK: Arithmetic Operations @@ -936,6 +1014,23 @@ extension Constant { } } +// MARK: Constant Pointer To Integer + +extension Constant where Repr: IntegralConstantRepresentation { + /// Creates a constant pointer-to-integer operation to convert the given constant + /// global pointer value to the given integer type. + /// + /// - parameter val: The pointer value. + /// - parameter intType: The destination integer type. + /// + /// - returns: An constant value representing the constant value of the given + /// pointer converted to the given integer type. + public static func pointerToInt(_ val: IRConstant, _ intType: IntType) -> Constant { + precondition(val.isConstant, "May only convert global constant pointers to integers") + return Constant(llvm: LLVMConstPtrToInt(val.asLLVM(), intType.asLLVM())) + } +} + // MARK: Struct Operations extension Constant where Repr == Struct { @@ -946,10 +1041,48 @@ extension Constant where Repr == Struct { /// of the aggregate object are indexed. /// /// - returns: The value in the struct at the provided index. - public func getElement(indices: [Int]) -> IRValue { + public func getElement(indices: [Int]) -> IRConstant { var indices = indices.map({ UInt32($0) }) return indices.withUnsafeMutableBufferPointer { buf in - return LLVMConstExtractValue(asLLVM(), buf.baseAddress, UInt32(buf.count)) + return Constant(llvm: LLVMConstExtractValue(asLLVM(), buf.baseAddress, UInt32(buf.count))) + } + } + + /// Build a constant `GEP` (Get Element Pointer) instruction with a resultant + /// value that is undefined if the address is outside the actual underlying + /// allocated object and not the address one-past-the-end. + /// + /// The `GEP` instruction is often the source of confusion. LLVM [provides a + /// document](http://llvm.org/docs/GetElementPtr.html) to answer questions + /// around its semantics and correct usage. + /// + /// - parameter indices: A list of indices that indicate which of the elements + /// of the aggregate object are indexed. + /// + /// - returns: A value representing the address of a subelement of the given + /// aggregate data structure value. + public func getElementPointer(indices: [IRConstant]) -> IRConstant { + var indices = indices.map({ $0.asLLVM() as LLVMValueRef? }) + return indices.withUnsafeMutableBufferPointer { buf in + return Constant(llvm: LLVMConstGEP(asLLVM(), buf.baseAddress, UInt32(buf.count))) + } + } + + /// Build a GEP (Get Element Pointer) instruction. + /// + /// The `GEP` instruction is often the source of confusion. LLVM [provides a + /// document](http://llvm.org/docs/GetElementPtr.html) to answer questions + /// around its semantics and correct usage. + /// + /// - parameter indices: A list of indices that indicate which of the elements + /// of the aggregate object are indexed. + /// + /// - returns: A value representing the address of a subelement of the given + /// aggregate data structure value. + public func inBoundsGetElementPointer(indices: [IRConstant]) -> IRConstant { + var indices = indices.map({ $0.asLLVM() as LLVMValueRef? }) + return indices.withUnsafeMutableBufferPointer { buf in + return Constant(llvm: LLVMConstInBoundsGEP(asLLVM(), buf.baseAddress, UInt32(buf.count))) } } } @@ -1034,6 +1167,13 @@ extension Constant where Repr == Floating { return lhs.remainder(rhs) } + /// A constant equality comparison between two values. + /// + /// - parameter lhs: The first value to compare. + /// - parameter rhs: The second value to compare. + /// + /// - returns: A constant integral value (i1) representing the result of the + /// comparision of the given operands. public static func ==(lhs: Constant, rhs: Constant) -> Constant { return Constant.equals(lhs, rhs) } diff --git a/Sources/LLVM/Context.swift b/Sources/LLVM/Context.swift new file mode 100644 index 00000000..30225c16 --- /dev/null +++ b/Sources/LLVM/Context.swift @@ -0,0 +1,62 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +/// A `Context` is an LLVM compilation session environment. +/// +/// A `Context` is a container for the global state of an execution of the +/// LLVM environment and tooling. It contains independent copies of global and +/// module-level entities like types, metadata attachments, and constants. +/// +/// An LLVM context is needed for interacting with LLVM in a concurrent +/// environment. Because a context maintains state independent of any other +/// context, it is recommended that each thread of execution be assigned a unique +/// context. LLVM's core infrastructure and API provides no locking guarantees +/// and no atomicity guarantees. +public class Context { + internal let llvm: LLVMContextRef + private let ownsContext: Bool + + /// Retrieves the global context instance. + /// + /// The global context is an particularly convenient instance managed by LLVM + /// itself. It is the default context provided for any operations that + /// require it. + /// + /// - WARNING: Failure to specify the correct context in concurrent + /// environments can lead to data corruption. In general, it is always + /// recommended that each thread of execution attempting to access the LLVM + /// API have its own `Context` instance, rather than rely on this global + /// context. + public static let global = Context(llvm: LLVMGetGlobalContext()!) + + /// Creates a new `Context` object. + public init() { + llvm = LLVMContextCreate() + ownsContext = true + } + + /// Creates a `Context` object from an `LLVMContextRef` object. + public init(llvm: LLVMContextRef, ownsContext: Bool = false) { + self.llvm = llvm + self.ownsContext = ownsContext + } + + /// Returns whether the given context is set to discard all value names. + /// + /// If true, only the names of GlobalValue objects will be available in + /// the IR. This can be used to save memory and processing time, especially + /// in release environments. + public var discardValueNames: Bool { + get { return LLVMContextShouldDiscardValueNames(self.llvm) != 0 } + set { LLVMContextSetDiscardValueNames(self.llvm, newValue.llvm) } + } + + /// Deinitialize this value and dispose of its resources. + deinit { + guard self.ownsContext else { + return + } + LLVMContextDispose(self.llvm) + } +} diff --git a/Sources/LLVM/DIBuilder.swift b/Sources/LLVM/DIBuilder.swift new file mode 100644 index 00000000..e3dde554 --- /dev/null +++ b/Sources/LLVM/DIBuilder.swift @@ -0,0 +1,1266 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +/// A `DIBuilder` is a helper object used to generate debugging information in +/// the form of LLVM metadata. A `DIBuilder` is usually paired with an +/// `IRBuilder` to allow for the generation of code and metadata in lock step. +public final class DIBuilder { + internal let llvm: LLVMDIBuilderRef + + /// The module this `DIBuilder` is associated with. + public let module: Module + + /// Initializes a new `DIBuilder` object. + /// + /// - Parameters: + /// - module: The parent module. + /// - allowUnresolved: If true, when this DIBuilder is finalized it will + /// collect unresolved nodes attached to the module in + /// order to resolve cycles + public init(module: Module, allowUnresolved: Bool = true) { + self.module = module + if allowUnresolved { + self.llvm = LLVMCreateDIBuilder(module.llvm) + } else { + self.llvm = LLVMCreateDIBuilderDisallowUnresolved(module.llvm) + } + } + + /// Construct any deferred debug info descriptors. + public func finalize() { + LLVMDIBuilderFinalize(self.llvm) + } + + /// Deinitialize this value and dispose of its resources. + deinit { + LLVMDisposeDIBuilder(self.llvm) + } +} + +// MARK: Declarations + +extension DIBuilder { + /// Builds a call to a debug intrinsic for declaring a local variable and + /// inserts it before a given instruction. + /// + /// This intrinsic provides information about a local element + /// (e.g. a variable) defined in some lexical scope. The variable does not + /// have to be physically represented in the source. + /// + /// Each variable may have at most one corresponding `llvm.dbg.declare`. A + /// variable declaration is not control-dependent: A variable is declared at + /// most once, and that declaration remains in effect until the lifetime of + /// that variable ends. + /// + /// `lldb.dbg.declare` can make optimizing code that needs accurate debug info + /// difficult because of these scoping constraints. + /// + /// - Parameters: + /// - variable: The IRValue of a variable to declare. + /// - before: The instruction before which the intrinsic will be inserted. + /// - metadata: Local variable metadata. + /// - expr: A "complex expression" that modifies the current + /// variable declaration. + /// - location: The location of the variable in source. + public func buildDeclare( + of variable: IRValue, + before: IRInstruction, + metadata: LocalVariableMetadata, + expr: ExpressionMetadata, + location: DebugLocation + ) { + guard let _ = LLVMDIBuilderInsertDeclareBefore( + self.llvm, variable.asLLVM(), metadata.asMetadata(), + expr.asMetadata(), location.asMetadata(), before.asLLVM()) else { + fatalError() + } + } + + /// Builds a call to a debug intrinsic for declaring a local variable and + /// inserts it at the end of a given basic block. + /// + /// This intrinsic provides information about a local element + /// (e.g. a variable) defined in some lexical scope. The variable does not + /// have to be physically represented in the source. + /// + /// Each variable may have at most one corresponding `llvm.dbg.declare`. A + /// variable declaration is not control-dependent: A variable is declared at + /// most once, and that declaration remains in effect until the lifetime of + /// that variable ends. + /// + /// `lldb.dbg.declare` can make optimizing code that needs accurate debug info + /// difficult because of these scoping constraints. + /// + /// - Parameters: + /// - variable: The IRValue of a variable to declare. + /// - block: The block in which the intrinsic will be placed. + /// - metadata: Local variable metadata. + /// - expr: A "complex expression" that modifies the current + /// variable declaration. + /// - location: The location of the variable in source. + public func buildDeclare( + of variable: IRValue, + atEndOf block: BasicBlock, + metadata: LocalVariableMetadata, + expr: ExpressionMetadata, + location: DebugLocation + ) { + guard let _ = LLVMDIBuilderInsertDeclareAtEnd( + self.llvm, variable.asLLVM(), metadata.asMetadata(), + expr.asMetadata(), location.asMetadata(), block.asLLVM()) else { + fatalError() + } + } + + /// Builds a call to a debug intrinsic for providing information about the + /// value of a local variable and inserts it before a given instruction. + /// + /// This intrinsic provides information to model the result of a source + /// variable being set to a new value. + /// + /// This intrinsic is built to describe the value of a source variable + /// *directly*. That is, the source variable may be a value or an address, + /// but the value for that variable provided to this intrinsic is considered + /// without interpretation to be the value of the given variable. + /// + /// - Parameters: + /// - value: The value to set the given variable to. + /// - metadata: Metadata for the given local variable. + /// - before: The instruction before which the intrinsic will be inserted. + /// - expr: A "complex expression" that modifies the given value. + /// - location: The location of the variable assignment in source. + public func buildDbgValue( + of value: IRValue, + to metadata: LocalVariableMetadata, + before: IRInstruction, + expr: ExpressionMetadata, + location: DebugLocation + ) { + guard let _ = LLVMDIBuilderInsertDbgValueBefore( + self.llvm, value.asLLVM(), metadata.asMetadata(), + expr.asMetadata(), location.asMetadata(), before.asLLVM()) else { + fatalError() + } + } + + /// Builds a call to a debug intrinsic for providing information about the + /// value of a local variable and inserts it before a given instruction. + /// + /// This intrinsic provides information to model the result of a source + /// variable being set to a new value. + /// + /// This intrinsic is built to describe the value of a source variable + /// *directly*. That is, the source variable may be a value or an address, + /// but the value for that variable provided to this intrinsic is considered + /// without interpretation to be the value of the given variable. + /// + /// - Parameters: + /// - value: The value to set the given variable to. + /// - metadata: Metadata for the given local variable. + /// - block: The block in which the intrinsic will be placed. + /// - expr: A "complex expression" that modifies the given value. + /// - location: The location of the variable assignment in source. + public func buildDbgValue( + of value: IRValue, + to metadata: LocalVariableMetadata, + atEndOf block: BasicBlock, + expr: ExpressionMetadata, + location: DebugLocation + ) { + guard let _ = LLVMDIBuilderInsertDbgValueAtEnd( + self.llvm, value.asLLVM(), metadata.asMetadata(), + expr.asMetadata(), location.asMetadata(), block.asLLVM()) else { + fatalError() + } + } +} + +// MARK: Scope Entities + +extension DIBuilder { + /// A CompileUnit provides an anchor for all debugging information generated + /// during this instance of compilation. + /// + /// - Parameters: + /// - language: The source programming language. + /// - file: The file descriptor for the source file. + /// - kind: The kind of debug info to generate. + /// - optimized: A flag that indicates whether optimization is enabled or + /// not when compiling the source file. Defaults to `false`. + /// - splitDebugInlining: If true, minimal debug info in the module is + /// emitted to facilitate online symbolication and stack traces in the + /// absence of .dwo/.dwp files when using Split DWARF. + /// - debugInfoForProfiling: A flag that indicates whether to emit extra + /// debug information for profile collection. + /// - flags: Command line options that are embedded in debug info for use + /// by third-party tools. + /// - splitDWARFPath: The path to the split DWARF file. + /// - identity: The identity of the tool that is compiling this source file. + /// - sysRoot: The Clang system root (the value of the `-isysroot` that's passed to clang). + /// - sdkRoot: The SDK root -- on Darwin platforms, this is the last component of the sysroot. + /// - Returns: A value representing a compilation-unit level scope. + public func buildCompileUnit( + for language: DWARFSourceLanguage, + in file: FileMetadata, + kind: DWARFEmissionKind, + optimized: Bool = false, + splitDebugInlining: Bool = false, + debugInfoForProfiling: Bool = false, + flags: [String] = [], + runtimeVersion: Int = 0, + splitDWARFPath: String = "", + identity: String = "", + sysRoot: String = "", + sdkRoot: String = "" + ) -> CompileUnitMetadata { + let allFlags = flags.joined(separator: " ") + guard let cu = LLVMDIBuilderCreateCompileUnit( + self.llvm, language.llvm, file.llvm, identity, identity.count, + optimized.llvm, + allFlags, allFlags.count, + UInt32(runtimeVersion), + splitDWARFPath, splitDWARFPath.count, + kind.llvm, + /*DWOId*/0, + splitDebugInlining.llvm, + debugInfoForProfiling.llvm, + sysRoot, + sysRoot.count, + sdkRoot, + sdkRoot.count + ) else { + fatalError() + } + return CompileUnitMetadata(llvm: cu) + } + + /// Create a file descriptor to hold debugging information for a file. + /// + /// Global variables and top level functions would be defined using this + /// context. File descriptors also provide context for source line + /// correspondence. + /// + /// - Parameters: + /// - name: The name of the file. + /// - directory: The directory the file resides in. + /// - Returns: A value represending metadata about a given file. + public func buildFile( + named name: String, in directory: String + ) -> FileMetadata { + guard let file = LLVMDIBuilderCreateFile( + self.llvm, name, name.count, directory, directory.count) + else { + fatalError("Failed to allocate metadata for a file") + } + return FileMetadata(llvm: file) + } + + /// Creates a new descriptor for a module with the specified parent scope. + /// + /// - Parameters: + /// - name: Module name. + /// - scope: The parent scope containing this module declaration. + /// - macros: A list of -D macro definitions as they would appear on a + /// command line. + /// - includePath: The path to the module map file. + /// - includeSystemRoot: The Clang system root (value of -isysroot). + public func buildModule( + named name: String, + scope: DIScope, + macros: [String] = [], + includePath: String = "", + includeSystemRoot: String = "" + ) -> ModuleMetadata { + let macros = macros.joined(separator: " ") + guard + let module = LLVMDIBuilderCreateModule( + self.llvm, scope.asMetadata(), name, name.count, + macros, macros.count, includePath, includePath.count, + includeSystemRoot, includeSystemRoot.count) + else { + fatalError("Failed to allocate metadata for a file") + } + return ModuleMetadata(llvm: module) + } + + /// Creates a new descriptor for a namespace with the specified parent scope. + /// + /// - Parameters: + /// - name: NameSpace name. + /// - scope: The parent scope containing this module declaration. + /// - exportsSymbols: Whether or not the namespace exports symbols, e.g. + /// this is true of C++ inline namespaces. + public func buildNameSpace( + named name: String, scope: DIScope, exportsSymbols: Bool + ) -> NameSpaceMetadata { + guard + let nameSpace = LLVMDIBuilderCreateNameSpace( + self.llvm, scope.asMetadata(), name, name.count, exportsSymbols.llvm) + else { + fatalError("Failed to allocate metadata for a file") + } + return NameSpaceMetadata(llvm: nameSpace) + } + + /// Create a new descriptor for the specified subprogram. + /// + /// - Parameters: + /// - name: Function name. + /// - linkageName: Mangled function name. + /// - scope: Function scope. + /// - file: File where this variable is defined. + /// - line: Line number. + /// - scopeLine: Set to the beginning of the scope this starts + /// - type: Function type. + /// - flags: Flags to emit DWARF attributes. + /// - isLocal: True if this function is not externally visible. + /// - isDefinition: True if this is a function definition. + /// - isOptimized: True if optimization is enabled. + public func buildFunction( + named name: String, linkageName: String, + scope: DIScope, file: FileMetadata, line: Int, scopeLine: Int, + type: DISubroutineType, + flags: DIFlags, + isLocal: Bool = true, isDefinition: Bool = true, + isOptimized: Bool = false + ) -> FunctionMetadata { + guard let fn = LLVMDIBuilderCreateFunction( + self.llvm, scope.asMetadata(), + name, name.count, linkageName, linkageName.count, + file.asMetadata(), UInt32(line), + type.asMetadata(), + isLocal.llvm, isDefinition.llvm, UInt32(scopeLine), + flags.llvm, isOptimized.llvm) + else { + fatalError("Failed to allocate metadata for a function") + } + return FunctionMetadata(llvm: fn) + } + + /// Create a descriptor for a lexical block with the specified parent context. + /// + /// - Parameters: + /// - scope: Parent lexical block. + /// - File: Source file. + /// - line: The line in the source file. + /// - column: The column in the source file. + /// + public func buildLexicalBlock( + scope: DIScope, file: FileMetadata, line: Int, column: Int + ) -> LexicalBlockMetadata { + guard let block = LLVMDIBuilderCreateLexicalBlock( + self.llvm, scope.asMetadata(), file.asMetadata(), + UInt32(line), UInt32(column)) + else { + fatalError("Failed to allocate metadata for a lexical block") + } + return LexicalBlockMetadata(llvm: block) + } + + /// Create a descriptor for a lexical block with a new file attached. + /// + /// - Parameters: + /// - scope: Lexical block. + /// - file: Source file. + /// - discriminator: DWARF path discriminator value. + public func buildLexicalBlockFile( + scope: DIScope, file: FileMetadata, discriminator: Int + ) -> LexicalBlockFileMetadata { + guard let block = LLVMDIBuilderCreateLexicalBlockFile( + self.llvm, scope.asMetadata(), file.asMetadata(), UInt32(discriminator)) + else { + fatalError("Failed to allocate metadata for a lexical block file") + } + return LexicalBlockFileMetadata(llvm: block) + } +} + +// MARK: Local Variables + +extension DIBuilder { + /// Create a new descriptor for a local auto variable. + /// + /// - Parameters: + /// - name: Variable name. + /// - scope: The local scope the variable is declared in. + /// - file: File where this variable is defined. + /// - line: Line number. + /// - type: Metadata describing the type of the variable. + /// - alwaysPreserve: If true, this descriptor will survive optimizations. + /// - flags: Flags. + /// - alignment: Variable alignment. + public func buildLocalVariable( + named name: String, + scope: DIScope, file: FileMetadata, line: Int, + type: DIType, alwaysPreserve: Bool = false, + flags: DIFlags = [], alignment: Alignment + ) -> LocalVariableMetadata { + guard let variable = LLVMDIBuilderCreateAutoVariable( + self.llvm, scope.asMetadata(), + name, name.count, file.asMetadata(), UInt32(line), + type.asMetadata(), alwaysPreserve.llvm, + flags.llvm, alignment.valueInBits()) + else { + fatalError("Failed to allocate metadata for a local variable") + } + return LocalVariableMetadata(llvm: variable) + } + + /// Create a new descriptor for a function parameter variable. + /// + /// - Parameters: + /// - name: Variable name. + /// - index: Unique argument number for this variable; starts at 1. + /// - scope: The local scope the variable is declared in. + /// - file: File where this variable is defined. + /// - line: Line number. + /// - type: Metadata describing the type of the variable. + /// - alwaysPreserve: If true, this descriptor will survive optimizations. + /// - flags: Flags. + public func buildParameterVariable( + named name: String, index: Int, + scope: DIScope, file: FileMetadata, line: Int, + type: DIType, alwaysPreserve: Bool = false, + flags: DIFlags = [] + ) -> LocalVariableMetadata { + guard let variable = LLVMDIBuilderCreateParameterVariable( + self.llvm, scope.asMetadata(), name, name.count, + UInt32(index), file.asMetadata(), UInt32(line), + type.asMetadata(), alwaysPreserve.llvm, flags.llvm) + else { + fatalError("Failed to allocate metadata for a parameter variable") + } + return LocalVariableMetadata(llvm: variable) + } +} + +// MARK: Debug Locations + +extension DIBuilder { + /// Creates a new debug location that describes a source location. + /// + /// - Parameters: + /// - location: The location of the line and column for this information. + /// If the location of the value is unknown, pass + /// `(line: 0, column: 0)`. + /// - scope: The scope this debug location resides in. + /// - inlinedAt: If this location has been inlined somewhere, the scope in + /// which it was inlined. Defaults to `nil`. + /// - Returns: A value representing a debug location. + public func buildDebugLocation( + at location : (line: Int, column: Int), + in scope: DIScope, + inlinedAt: DIScope? = nil + ) -> DebugLocation { + guard let loc = LLVMDIBuilderCreateDebugLocation( + self.module.context.llvm, UInt32(location.line), UInt32(location.column), + scope.asMetadata(), inlinedAt?.asMetadata()) + else { + fatalError("Failed to allocate metadata for a debug location") + } + return DebugLocation(llvm: loc) + } +} + +extension DIBuilder { + /// Create subroutine type. + /// + /// - Parameters: + /// - file: The file in which the subroutine resides. + /// - parameterTypes: An array of subroutine parameter types. + /// - returnType: The return type of the function, if any. + /// - flags: Flags to emit DWARF attributes. + public func buildSubroutineType( + in file: FileMetadata, + parameterTypes: [DIType], returnType: DIType? = nil, + flags: DIFlags = [] + ) -> DISubroutineType { + // The return type is always the first operand. + var diTypes = [returnType?.asMetadata()] + diTypes.append(contentsOf: parameterTypes.map { + return $0.asMetadata() as Optional + }) + return diTypes.withUnsafeMutableBufferPointer { buf in + guard let ty = LLVMDIBuilderCreateSubroutineType( + self.llvm, file.asMetadata(), + buf.baseAddress!, UInt32(buf.count), + flags.llvm) + else { + fatalError("Failed to allocate metadata") + } + return DISubroutineType(llvm: ty) + } + } + + /// Create a debugging information entry for an enumeration. + /// + /// - Parameters: + /// - name: Enumeration name. + /// - scope: Scope in which this enumeration is defined. + /// - file: File where this member is defined. + /// - line: Line number. + /// - size: Member size. + /// - alignment: Member alignment. + /// - elements: Enumeration elements. + /// - numElements: Number of enumeration elements. + /// - underlyingType: Underlying type of a C++11/ObjC fixed enum. + public func buildEnumerationType( + named name: String, + scope: DIScope, file: FileMetadata, line: Int, + size: Size, alignment: Alignment, + elements: [DIType], underlyingType: DIType + ) -> DIType { + var diTypes = elements.map { $0.asMetadata() as Optional } + return diTypes.withUnsafeMutableBufferPointer { buf in + guard let ty = LLVMDIBuilderCreateEnumerationType( + self.llvm, scope.asMetadata(), + name, name.count, file.asMetadata(), UInt32(line), + size.valueInBits(), alignment.valueInBits(), + buf.baseAddress!, UInt32(buf.count), + underlyingType.asMetadata()) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + } + + /// Create a debugging information entry for a union. + /// + /// - Parameters: + /// - name: Union name. + /// - scope: Scope in which this union is defined. + /// - file: File where this member is defined. + /// - line: Line number. + /// - size: Member size. + /// - alignment: Member alignment. + /// - flags: Flags to encode member attribute, e.g. private + /// - elements: Union elements. + /// - runtimeVersion: Optional parameter, Objective-C runtime version. + /// - uniqueID: A unique identifier for the union. + public func buildUnionType( + named name: String, + scope: DIScope, file: FileMetadata, line: Int, + size: Size, alignment: Alignment, flags: DIFlags, + elements: [DIType], + runtimeVersion: Int = 0, uniqueID: String = "" + ) -> DIType { + var diTypes = elements.map { $0.asMetadata() as Optional } + return diTypes.withUnsafeMutableBufferPointer { buf in + guard let ty = LLVMDIBuilderCreateUnionType( + self.llvm, scope.asMetadata(), + name, name.count, file.asMetadata(), UInt32(line), + size.valueInBits(), alignment.valueInBits(), + flags.llvm, buf.baseAddress!, UInt32(buf.count), + UInt32(runtimeVersion), uniqueID, uniqueID.count) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + } + + /// Create a debugging information entry for an array. + /// + /// - Parameters: + /// - elementType: Metadata describing the type of the elements. + /// - size: The total size of the array. + /// - alignment: The alignment of the array. + /// - subscripts: A list of ranges of valid subscripts into the array. For + /// unbounded arrays, pass the unchecked range `-1...0`. + public func buildArrayType( + of elementType: DIType, + size: Size, alignment: Alignment, + subscripts: [Range] = [] + ) -> DIType { + var diSubs = subscripts.map { + LLVMDIBuilderGetOrCreateSubrange(self.llvm, + Int64($0.lowerBound), Int64($0.count)) + } + return diSubs.withUnsafeMutableBufferPointer { buf in + guard let ty = LLVMDIBuilderCreateArrayType( + self.llvm, size.rawValue, alignment.valueInBits(), + elementType.asMetadata(), + buf.baseAddress!, UInt32(buf.count)) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + } + + /// Create a debugging information entry for a vector. + /// + /// - Parameters: + /// - elementType: Metadata describing the type of the elements. + /// - size: The total size of the array. + /// - alignment: The alignment of the array. + /// - subscripts: A list of ranges of valid subscripts into the array. For + /// unbounded arrays, pass the unchecked range `-1...0`. + public func buildVectorType( + of elementType: DIType, + size: Size, alignment: Alignment, + subscripts: [Range] = [] + ) -> DIType { + var diSubs = subscripts.map { + LLVMDIBuilderGetOrCreateSubrange(self.llvm, + Int64($0.lowerBound), Int64($0.count)) + } + return diSubs.withUnsafeMutableBufferPointer { buf in + guard let ty = LLVMDIBuilderCreateVectorType( + self.llvm, size.rawValue, alignment.valueInBits(), + elementType.asMetadata(), + buf.baseAddress!, UInt32(buf.count)) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + } + + /// Create a debugging information entry for a DWARF unspecified type. + /// + /// Some languages have constructs in which a type may be left unspecified or + /// the absence of a type may be explicitly indicated. For example, C++ + /// permits using the `auto` return type specifier for the return type of a + /// member function declaration. The actual return type is deduced based on + /// the definition of the function, so it may not be known when the function + /// is declared. The language implementation can provide an unspecified type + /// entry with the name `auto` which can be referenced by the return type + /// attribute of a function declaration entry. When the function is later + /// defined, the `subprogram` entry for the definition includes a reference to + /// the actual return type. + /// + /// - Parameter name: The name of the type + public func buildUnspecifiedType(named name: String) -> DIType { + guard let ty = LLVMDIBuilderCreateUnspecifiedType( + self.llvm, name, name.count) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a debugging information entry for a basic type. + /// + /// - Parameters: + /// - name: Type name. + /// - encoding: The basic type encoding + /// - size: Size of the type. + public func buildBasicType( + named name: String, encoding: DIAttributeTypeEncoding, flags: DIFlags, size: Size + ) -> DIType { + guard let ty = LLVMDIBuilderCreateBasicType( + self.llvm, name, name.count, + size.valueInBits(), encoding.llvm, flags.llvm) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a debugging information entry for a pointer. + /// + /// - Parameters: + /// - pointee: Type pointed by this pointer. + /// - size: The size of the pointer value. + /// - alignment: The alignment of the pointer. + /// - addressSpace: The address space the pointer type reside in. + /// - name: The name of the pointer type. + public func buildPointerType( + pointee: DIType, size: Size, alignment: Alignment, + addressSpace: AddressSpace = .zero, name: String = "" + ) -> DIType { + guard let ty = LLVMDIBuilderCreatePointerType( + self.llvm, pointee.asMetadata(), + size.valueInBits(), alignment.valueInBits(), + UInt32(addressSpace.rawValue), name, name.count) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a debugging information entry for a struct. + /// + /// - Parameters: + /// - name: Struct name. + /// - scope: Scope in which this struct is defined. + /// - file: File where this member is defined. + /// - line: Line number. + /// - size: The total size of the struct and its members. + /// - alignment: The alignment of the struct. + /// - flags: Flags to encode member attributes. + /// - elements: Struct elements. + /// - vtableHolder: The object containing the vtable for the struct. + /// - runtimeVersion: Optional parameter, Objective-C runtime version. + /// - uniqueId: A unique identifier for the struct. + public func buildStructType( + named name: String, + scope: DIScope, file: FileMetadata, line: Int, + size: Size, alignment: Alignment, flags: DIFlags = [], + baseType: DIType? = nil, elements: [DIType] = [], + vtableHolder: DIType? = nil, runtimeVersion: Int = 0, uniqueID: String = "" + ) -> DIType { + var diEls = elements.map { $0.asMetadata() as Optional } + return diEls.withUnsafeMutableBufferPointer { buf in + guard let ty = LLVMDIBuilderCreateStructType( + self.llvm, scope.asMetadata(), name, name.count, + file.asMetadata(), UInt32(line), + size.valueInBits(), alignment.valueInBits(), + flags.llvm, + baseType?.asMetadata(), + buf.baseAddress!, UInt32(buf.count), UInt32(runtimeVersion), + vtableHolder?.asMetadata(), uniqueID, uniqueID.count) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + } + + /// Create a debugging information entry for a member. + /// + /// - Parameters: + /// - parentType: Parent type. + /// - scope: Member scope. + /// - name: Member name. + /// - file: File where this member is defined. + /// - line: Line number. + /// - size: Member size. + /// - alignment: Member alignment. + /// - offset: Member offset. + /// - flags: Flags to encode member attributes. + public func buildMemberType( + of parentType: DIType, scope: DIScope, name: String, + file: FileMetadata, line: Int, + size: Size, alignment: Alignment, offset: Size, flags: DIFlags = [] + ) -> DIType { + guard let ty = LLVMDIBuilderCreateMemberType( + self.llvm, scope.asMetadata(), name, name.count, file.asMetadata(), + UInt32(line), + size.valueInBits(), alignment.valueInBits(), + offset.rawValue, + flags.llvm, parentType.asMetadata()) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a debugging information entry for a C++ static data member. + /// + /// - Parameters: + /// - parentType: Type of the static member. + /// - scope: Member scope. + /// - name: Member name. + /// - file: File where this member is declared. + /// - line: Line number. + /// - alignment: Member alignment. + /// - flags: Flags to encode member attributes. + /// - initialValue: Constant initializer of the member. + public func buildStaticMemberType( + of parentType: DIType, scope: DIScope, name: String, file: FileMetadata, + line: Int, alignment: Alignment, flags: DIFlags = [], + initialValue: IRConstant? = nil + ) -> DIType { + guard let ty = LLVMDIBuilderCreateStaticMemberType( + self.llvm, scope.asMetadata(), name, name.count, + file.asMetadata(), UInt32(line), + parentType.asMetadata(), flags.llvm, + initialValue?.asLLVM(), alignment.valueInBits()) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a debugging information entry for a pointer to member. + /// + /// - Parameters: + /// - pointee: Type pointed to by this pointer. + /// - baseType: Type for which this pointer points to members of. + /// - size: Size. + /// - alignment: Alignment. + /// - flags: Flags. + public func buildMemberPointerType( + pointee: DIType, baseType: DIType, + size: Size, alignment: Alignment, + flags: DIFlags = [] + ) -> DIType { + guard let ty = LLVMDIBuilderCreateMemberPointerType( + self.llvm, pointee.asMetadata(), baseType.asMetadata(), + size.valueInBits(), alignment.valueInBits(), + flags.llvm) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a uniqued DIType* clone with FlagObjectPointer and + /// FlagArtificial set. + /// + /// - Parameters: + /// - pointee: The underlying type to which this pointer points. + public func buildObjectPointerType(pointee: DIType) -> DIType { + guard let ty = LLVMDIBuilderCreateObjectPointerType( + self.llvm, pointee.asMetadata()) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a debugging information entry for a qualified type, e.g. 'const int'. + /// + /// - Parameters: + /// - tag: Tag identifying type. + /// - type: Base Type. + public func buildQualifiedType(_ tag: DWARFTag, _ type: DIType) -> DIType { + guard let ty = LLVMDIBuilderCreateQualifiedType( + self.llvm, tag.rawValue, type.asMetadata()) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a debugging information entry for a c++ style reference or rvalue + /// reference type. + /// + /// - Parameters: + /// - tag: Tag identifying type. + /// - type: Base Type. + public func buildReferenceType(_ tag: DWARFTag, _ type: DIType) -> DIType { + guard let ty = LLVMDIBuilderCreateReferenceType( + self.llvm, tag.rawValue, type.asMetadata()) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create C++11 nullptr type. + public func buildNullPtrType() -> DIType { + guard let ty = LLVMDIBuilderCreateNullPtrType(self.llvm) else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } +} + +extension DIBuilder { + /// Create a debugging information entry for a typedef. + /// + /// - Parameters: + /// - type: Original type. + /// - name: Typedef name. + /// - alignment: Alignment of the type. + /// - scope: The surrounding context for the typedef. + /// - file: File where this type is defined. + /// - line: Line number. + public func buildTypedef( + of type: DIType, + name: String, + alignment: Alignment, + scope: DIScope, + file: FileMetadata, + line: Int + ) -> DIType { + guard let ty = LLVMDIBuilderCreateTypedef( + self.llvm, type.asMetadata(), name, name.count, + file.asMetadata(), UInt32(line), scope.asMetadata(), + alignment.valueInBits()) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a debugging information entry to establish inheritance relationship + /// between two types. + /// + /// - Parameters: + /// - derived: Original type. + /// - base: Base type. Ty is inherits from base. + /// - baseOffset: Base offset. + /// - virtualBasePointerOffset: Virtual base pointer offset. + /// - flags: Flags to describe inheritance attribute, e.g. private + public func buildInheritance( + of derived: DIType, to base: DIType, + baseOffset: Size, virtualBasePointerOffset: Size, flags: DIFlags = [] + ) -> DIType { + guard let ty = LLVMDIBuilderCreateInheritance( + self.llvm, derived.asMetadata(), + base.asMetadata(), + baseOffset.valueInBits(), + UInt32(virtualBasePointerOffset.valueInBits()), + flags.llvm) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a permanent forward-declared type. + /// + /// - Parameters: + /// - name: Type name. + /// - tag: A unique tag for this type. + /// - scope: Type scope. + /// - file: File where this type is defined. + /// - line: Line number where this type is defined. + /// - size: Member size. + /// - alignment: Member alignment. + /// - runtimeLanguage: Indicates runtime version for languages like + /// Objective-C. + /// - uniqueID: A unique identifier for the type. + public func buildForwardDeclaration( + named name: String, tag: DWARFTag, + scope: DIScope, file: FileMetadata, line: Int, + size: Size, alignment: Alignment, + runtimeLanguage: Int = 0, uniqueID: String = "" + ) -> DIType { + guard let ty = LLVMDIBuilderCreateForwardDecl( + self.llvm, tag.rawValue, name, name.count, + scope.asMetadata(), file.asMetadata(), UInt32(line), + UInt32(runtimeLanguage), + size.valueInBits(), alignment.valueInBits(), + uniqueID, uniqueID.count) else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a temporary forward-declared type. + /// + /// - Parameters: + /// - name: Type name. + /// - tag: A unique tag for this type. + /// - scope: Type scope. + /// - file: File where this type is defined. + /// - line: Line number where this type is defined. + /// Objective-C. + /// - size: Member size. + /// - alignment: Member alignment. + /// - flags: Flags. + /// - runtimeVersion: Indicates runtime version for languages like + /// - uniqueID: A unique identifier for the type. + public func buildReplaceableCompositeType( + named name: String, tag: DWARFTag, + scope: DIScope, file: FileMetadata, line: Int, + size: Size, alignment: Alignment, flags: DIFlags = [], + runtimeVersion: Int = 0, uniqueID: String = "" + ) -> DIType { + guard let ty = LLVMDIBuilderCreateReplaceableCompositeType( + self.llvm, tag.rawValue, name, name.count, + scope.asMetadata(), file.asMetadata(), UInt32(line), + UInt32(runtimeVersion), + size.valueInBits(), alignment.valueInBits(), + flags.llvm, + uniqueID, uniqueID.count) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a debugging information entry for a bit field member. + /// + /// - Parameters: + /// - name: Member name. + /// - type: Parent type. + /// - scope: Member scope. + /// - file: File where this member is defined. + /// - line: Line number. + /// - size: Member size. + /// - offset: Member offset. + /// - storageOffset: Member storage offset. + /// - flags: Flags to encode member attribute. + public func buildBitFieldMemberType( + named name: String, type: DIType, + scope: DIScope, file: FileMetadata, line: Int, + size: Size, offset: Size, storageOffset: Size, + flags: DIFlags = [] + ) -> DIType { + guard let ty = LLVMDIBuilderCreateBitFieldMemberType( + self.llvm, scope.asMetadata(), name, name.count, + file.asMetadata(), UInt32(line), + size.valueInBits(), offset.valueInBits(), + storageOffset.valueInBits(), + flags.llvm, type.asMetadata()) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a debugging information entry for a class. + /// + /// - name: Class name. + /// - baseType: Debug info of the base class of this type. + /// - scope: Scope in which this class is defined. + /// - file: File where this member is defined. + /// - line: Line number. + /// - size: Member size. + /// - alignment: Member alignment. + /// - offset: Member offset. + /// - flags: Flags to encode member attribute, e.g. private. + /// - elements: Class members. + /// - vtableHolder: Debug info of the base class that contains vtable + /// for this type. This is used in `DW_AT_containing_type`. + /// - uniqueID: A unique identifier for the type. + public func buildClassType( + named name: String, derivedFrom baseType: DIType?, + scope: DIScope, file: FileMetadata, line: Int, + size: Size, alignment: Alignment, offset: Size, flags: DIFlags, + elements: [DIType] = [], + vtableHolder: DIType? = nil, uniqueID: String = "" + ) -> DIType { + var diEls = elements.map { $0.asMetadata() as Optional } + return diEls.withUnsafeMutableBufferPointer { buf in + guard let ty = LLVMDIBuilderCreateClassType( + self.llvm, scope.asMetadata(), name, name.count, + file.asMetadata(), UInt32(line), + size.valueInBits(), alignment.valueInBits(), + offset.rawValue, flags.llvm, + baseType?.asMetadata(), + buf.baseAddress!, UInt32(buf.count), + vtableHolder?.asMetadata(), nil, uniqueID, uniqueID.count) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + } + + /// Create a uniqued DIType* clone with FlagArtificial set. + /// + /// - Parameters: + /// - type: The underlying type. + public func buildArtificialType(_ type: DIType) -> DIType { + guard let ty = LLVMDIBuilderCreateArtificialType( + self.llvm, type.asMetadata()) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } +} + +// MARK: Imported Entities + +extension DIBuilder { + /// Create a descriptor for an imported module. + /// + /// - Parameters: + /// - context: The scope this module is imported into + /// - namespace: The namespace being imported here. + /// - file: File where the declaration is located. + /// - line: Line number of the declaration. + public func buildImportedModule( + in context: DIScope, namespace: NameSpaceMetadata, + file: FileMetadata, line: Int + ) -> ImportedEntityMetadata { + guard let mod = LLVMDIBuilderCreateImportedModuleFromNamespace( + self.llvm, context.asMetadata(), + namespace.asMetadata(), file.asMetadata(), UInt32(line)) + else { + fatalError("Failed to allocate metadata") + } + return ImportedEntityMetadata(llvm: mod) + } + + /// Create a descriptor for an imported module. + /// + /// - Parameters: + /// - context: The scope this module is imported into. + /// - aliasee: An aliased namespace. + /// - file: File where the declaration is located. + /// - line: Line number of the declaration. + public func buildImportedModule( + in context: DIScope, aliasee: ImportedEntityMetadata, + file: FileMetadata, line: Int + ) -> ImportedEntityMetadata { + guard let mod = LLVMDIBuilderCreateImportedModuleFromNamespace( + self.llvm, context.asMetadata(), aliasee.asMetadata(), + file.asMetadata(), UInt32(line)) + else { + fatalError("Failed to allocate metadata") + } + return ImportedEntityMetadata(llvm: mod) + } + + /// Create a descriptor for an imported module. + /// + /// - Parameters: + /// - context: The scope this module is imported into. + /// - module: The module being imported here + /// - file: File where the declaration is located. + /// - line: Line number of the declaration. + public func buildImportedModule( + in context: DIScope, module: ModuleMetadata, file: FileMetadata, line: Int + ) -> ImportedEntityMetadata { + guard let mod = LLVMDIBuilderCreateImportedModuleFromModule( + self.llvm, context.asMetadata(), module.asMetadata(), + file.asMetadata(), UInt32(line)) + else { + fatalError("Failed to allocate metadata") + } + return ImportedEntityMetadata(llvm: mod) + } + + /// Create a descriptor for an imported function. + /// + /// - Parameters: + /// - context: The scope this module is imported into. + /// - declaration: The declaration (or definition) of a function, type, or + /// variable. + /// - file: File where the declaration is located. + /// - line: Line number of the declaration. + /// - name: The name of the imported declaration. + public func buildImportedDeclaration( + in context: DIScope, declaration: IRMetadata, + file: FileMetadata, line: Int, name: String = "" + ) -> ImportedEntityMetadata { + guard let mod = LLVMDIBuilderCreateImportedDeclaration( + self.llvm, context.asMetadata(), + declaration.asMetadata(), + file.asMetadata(), UInt32(line), name, name.count) + else { + fatalError("Failed to allocate metadata") + } + return ImportedEntityMetadata(llvm: mod) + } +} + +// MARK: Objective-C + +extension DIBuilder { + /// Create a debugging information entry for Objective-C instance variable. + /// + /// - Parameters: + /// - property: The property associated with this ivar. + /// - name: Member name. + /// - type: Type. + /// - file: File where this member is defined. + /// - line: Line number. + /// - size: Member size. + /// - alignment: Member alignment. + /// - offset: Member offset. + /// - flags: Flags to encode member attributes. + public func buildObjCIVar( + for property: ObjectiveCPropertyMetadata, name: String, type: DIType, + file: FileMetadata, line: Int, + size: Size, alignment: Alignment, offset: Size, flags: DIFlags = [] + ) -> DIType { + guard let ty = LLVMDIBuilderCreateObjCIVar( + self.llvm, name, name.count, file.asMetadata(), UInt32(line), + size.valueInBits(), alignment.valueInBits(), + offset.rawValue, flags.llvm, type.asMetadata(), property.asMetadata()) + else { + fatalError("Failed to allocate metadata") + } + return DIOpaqueType(llvm: ty) + } + + /// Create a debugging information entry for Objective-C property. + /// + /// - Parameters: + /// - name: Property name. + /// - type: Type. + /// - file: File where this property is defined. + /// - line: Line number. + /// - getter: Name of the Objective C property getter selector. + /// - setter: Name of the Objective C property setter selector. + /// - propertyAttributes: Objective C property attributes. + public func buildObjCProperty( + named name: String, type: DIType, + file: FileMetadata, line: Int, + getter: String, setter: String, + propertyAttributes: ObjectiveCPropertyAttribute + ) -> ObjectiveCPropertyMetadata { + guard let ty = LLVMDIBuilderCreateObjCProperty( + self.llvm, name, name.count, file.asMetadata(), UInt32(line), + getter, getter.count, setter, setter.count, + propertyAttributes.rawValue, type.asMetadata()) + else { + fatalError("Failed to allocate metadata") + } + return ObjectiveCPropertyMetadata(llvm: ty) + } +} + +extension DIBuilder { + /// Create a new descriptor for the specified variable which has a complex + /// address expression for its address. + /// + /// - Parameters: + /// - expression: An array of complex address operations. + public func buildExpression(_ expression: [DWARFExpression]) -> ExpressionMetadata { + var expr = expression.flatMap { $0.rawValue } + let count = expr.count + return expr.withUnsafeMutableBytes { raw in + let rawVal = raw.bindMemory(to: Int64.self) + guard let expr = LLVMDIBuilderCreateExpression( + self.llvm, rawVal.baseAddress!, count) + else { + fatalError("Failed to allocate metadata") + } + return ExpressionMetadata(llvm: expr) + } + } + + /// Create a new descriptor for the specified variable that does not have an + /// address, but does have a constant value. + /// + /// - Parameters: + /// - value: The constant value. + public func buildConstantExpresion(_ value: Int) -> ExpressionMetadata { + guard let expr = LLVMDIBuilderCreateConstantValueExpression( + self.llvm, Int64(value)) + else { + fatalError("Failed to allocate metadata") + } + return ExpressionMetadata(llvm: expr) + } + + /// Create a new descriptor for the specified variable. + /// + /// - Parameters: + /// - name: Name of the variable. + /// - linkageName: Mangled name of the variable. + /// - type: Variable Type. + /// - scope: Variable scope. + /// - file: File where this variable is defined. + /// - line: Line number. + /// - isLocal: Boolean flag indicate whether this variable is + /// externally visible or not. + /// - expression: The location of the global relative to the attached + /// GlobalVariable. + /// - declaration: Reference to the corresponding declaration. + /// - alignment: Variable alignment + public func buildGlobalExpression( + named name: String, linkageName: String, type: DIType, + scope: DIScope, file: FileMetadata, line: Int, + isLocal: Bool = true, + expression: ExpressionMetadata? = nil, + declaration: IRMetadata? = nil, + alignment: Alignment + ) -> ExpressionMetadata { + guard let ty = LLVMDIBuilderCreateGlobalVariableExpression( + self.llvm, scope.asMetadata(), + name, name.count, linkageName, linkageName.count, + file.asMetadata(), UInt32(line), + type.asMetadata(), + isLocal.llvm, + expression?.asMetadata(), declaration?.asMetadata(), + alignment.valueInBits()) + else { + fatalError("Failed to allocate metadata") + } + return ExpressionMetadata(llvm: ty) + } +} diff --git a/Sources/LLVM/DWARFExpression.swift b/Sources/LLVM/DWARFExpression.swift new file mode 100644 index 00000000..aac77b3e --- /dev/null +++ b/Sources/LLVM/DWARFExpression.swift @@ -0,0 +1,1020 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +/// DWARF expressions describe how to compute a value or specify a location. +/// They are expressed in terms of DWARF operations that operate on a stack of +/// values. +/// +/// A DWARF expression is encoded as a stream of operations, each consisting of +/// an opcode followed by zero or more literal operands. +public enum DWARFExpression { + // MARK: Literals + + /// Encodes a single machine address value whose size is the size of an + /// address on the target machine. + case addr(UInt64) + + /// Encodes the unsigned literal value 0. + case lit0 + /// Encodes the unsigned literal value 1. + case lit1 + /// Encodes the unsigned literal value 2. + case lit2 + /// Encodes the unsigned literal value 3. + case lit3 + /// Encodes the unsigned literal value 4. + case lit4 + /// Encodes the unsigned literal value 5. + case lit5 + /// Encodes the unsigned literal value 6. + case lit6 + /// Encodes the unsigned literal value 7. + case lit7 + /// Encodes the unsigned literal value 8. + case lit8 + /// Encodes the unsigned literal value 9. + case lit9 + /// Encodes the unsigned literal value 10. + case lit10 + /// Encodes the unsigned literal value 11. + case lit11 + /// Encodes the unsigned literal value 12. + case lit12 + /// Encodes the unsigned literal value 13. + case lit13 + /// Encodes the unsigned literal value 14. + case lit14 + /// Encodes the unsigned literal value 15. + case lit15 + /// Encodes the unsigned literal value 16. + case lit16 + /// Encodes the unsigned literal value 17. + case lit17 + /// Encodes the unsigned literal value 18. + case lit18 + /// Encodes the unsigned literal value 19. + case lit19 + /// Encodes the unsigned literal value 20. + case lit20 + /// Encodes the unsigned literal value 21. + case lit21 + /// Encodes the unsigned literal value 22. + case lit22 + /// Encodes the unsigned literal value 23. + case lit23 + /// Encodes the unsigned literal value 24. + case lit24 + /// Encodes the unsigned literal value 25. + case lit25 + /// Encodes the unsigned literal value 26. + case lit26 + /// Encodes the unsigned literal value 27. + case lit27 + /// Encodes the unsigned literal value 28. + case lit28 + /// Encodes the unsigned literal value 29. + case lit29 + /// Encodes the unsigned literal value 30. + case lit30 + /// Encodes the unsigned literal value 31. + case lit31 + + /// Encodes a 1-byte unsigned integer constant. + case const1u(UInt8) + /// Encodes a 1-byte signed integer constant. + case const1s(Int8) + /// Encodes a 2-byte unsigned integer constant. + case const2u(UInt16) + /// Encodes a 2-byte signed integer constant. + case const2s(Int16) + /// Encodes a 4-byte unsigned integer constant. + case const4u(UInt32) + /// Encodes a 4-byte signed integer constant. + case const4s(Int32) + /// Encodes a 8-byte unsigned integer constant. + case const8u(UInt64) + /// Encodes a 8-byte signed integer constant. + case const8s(Int64) + /// Encodes a little-endian base-128 unsigned integer constant. + case constu(UInt64) + /// Encodes a little-endian base-128 signed integer constant. + case consts(Int64) + /// Encodes an unsigned little-endian base-128 value, which is a zero-based + /// index into the `.debug_addr` section where a machine address is stored. + /// This index is relative to the value of the `DW_AT_addr_base` attribute + /// of the associated compilation unit. + case addrx(UInt64) + /// Encodes an unsigned little-endian base-128 value, which is a zero-based + /// index into the `.debug_addr` section where a constant, the size of a + /// machine address, is stored. This index is relative to the value of the + /// `DW_AT_addr_base` attribute of the associated compilation unit. + /// + /// This operation is provided for constants that require link-time relocation + /// but should not be interpreted by the consumer as a relocatable address ( + /// for example, offsets to thread-local storage). + case constx(UInt64) + + // MARK: Register Values + + /// Provides a signeed little-endian base-128 offset from the address + /// specified by the location description in the `DW_AT_frame_base` attribute + /// of the current function. + case fbreg(Int64) + + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 0. + case breg0(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 1. + case breg1(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 2. + case breg2(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 3. + case breg3(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 4. + case breg4(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 5. + case breg5(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 6. + case breg6(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 7. + case breg7(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 8. + case breg8(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 9. + case breg9(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 10. + case breg10(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 11. + case breg11(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 12. + case breg12(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 13. + case breg13(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 14. + case breg14(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 15. + case breg15(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 16. + case breg16(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 17. + case breg17(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 18. + case breg18(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 19. + case breg19(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 20. + case breg20(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 21. + case breg21(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 22. + case breg22(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 23. + case breg23(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 24. + case breg24(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 25. + case breg25(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 26. + case breg26(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 27. + case breg27(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 28. + case breg28(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 29. + case breg29(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 30. + case breg30(Int64) + /// The single operand of the breg operation provides a signed little-endian + /// base-128 offset from the contents of register 31. + case breg31(Int64) + + /// Provides the sum of two values specified by its two operands. The first + /// operand being a register number which is in unsigned little-endian + /// base-128 form. The second being an offset in signed little-endian + /// base-128 form. + case bregx(UInt64, Int64) + + /// Provides an operation with three operands: The first is an unsigned + /// little-endian base-128 integer that represents the offset of a debugging + /// information entry in the current compilation unit, which must be + /// a base type entry that provides the type of the constant provided. + /// The second operand is a 1-byte unsigned integer that specifies the + /// size of the constant value, which is the same size as the base type + /// referenced by the first operand. The third operand is a sequence of bytes + /// of the given size that is interpreted as a value of the referenced type. + case constType(DIAttributeTypeEncoding, UInt8, [UInt8]) + + /// Provides the contents of a given register interpreted as a value of a + /// given type. The first operand is an unsigned little-endian base-128 + /// number which identifies a register whose contents are pushed onto the + /// stack. The second operand is an unsigned little-endian base-128 number + /// that represents the offset of a debugging information entry in the current + /// compilation unit which must have base type. + case regvalType(UInt64, DIAttributeTypeEncoding) + + // MARK: Stack Operations + + /// Duplicates the value (including its type identifier) at the top of the + /// stack. + case dup + /// Pops the value (including its type identifier) at the top of the stack. + case drop + /// Provides a 1-byte index that is used to index into the stack. A copy of + /// stack entry at that index is pushed onto the stack. + case pick(UInt8) + /// Duplicates the entry currently second in the stack and pushes it onto the + /// stack. + /// + /// This operation is equivalent to `.pick(1)`. + case over + /// Swaps the top two stack entries. The entry at the top of the stack + /// (including its type identifier) becomes the second stack entry, and the + /// second entry (including its type identifier) becomes the top of the stack. + case swap + /// Rotates the first three stack entries. The entry at the top of the stack + /// (including its type identifier) becomes the third stack entry, the second + /// stack entry (including its type identifier) becomes the top of the stack, + /// and the third entry (including its type identifier) becomes the second + /// entry. + case rot + /// Pops the top stack entry and treats it as an address. + /// + /// The popped value must have an integral type. The value retrieved from + /// that address is pushed, and has the generic type. The size of the data + /// retrieved from the dereferenced address is the size of an address on the + /// target machine. + case deref + /// Pops the top stack entry and treats it as an address. + /// + /// The popped value must have an integral type. The value retrieved from + /// that address is pushed, and has the generic type. The size of the data + /// retrieved from the dereferenced address is specified by the + /// operand, whose value is a 1-byte unsigned integral constant. The data + /// retrieved is zero-extended to the size of an address on the target machine + /// before being pushed onto the expression stack. + case derefSize(UInt8) + /// Pops the top stack entry and treats it as an address. + /// + /// The popped value must have an integral type. The size of the data + /// retrieved from the dereferenced address is specified by the first + /// operand, whose value is a 1-byte unsigned integral constant. The data + /// retrieved is zero-extended to the size of an address on the target machine + /// before being pushed onto the expression stack. The second operand is an + /// unsigned little-endian base-128 integer that represents the offset of a + /// debugging information entry in the current compilation unit which must + /// have a base type entry that provides the type of the data pushed. + case derefType(UInt8, UInt64) + /// Provides an extended dereference mechanism. + /// + /// The entry at the top of the stack is treated as an address. The second + /// stack entry is treated as an "address space identifier" for those + /// architectures that support multiple address spaces. Both of these + /// entries must have integral type identifiers. + /// + /// The top two stack elements are popped, and a data item is retrieved + /// through an implementation-defined address calculation and pushed as the + /// new stack top together with the generic type identifier. The size of the + /// data retrieved from the dereferenced address is the size of the + /// generic type. + case xderef + /// Provides an extended dereference mechanism. + /// + /// The entry at the top of the stack is treated as an address. The second + /// stack entry is treated as an "address space identifier" for those + /// architectures that support multiple address spaces. Both of these + /// entries must have integral type identifiers. + /// + /// The top two stack elements are popped, and a data item is retrieved + /// through an implementation-defined address calculation and pushed as the + /// new stack top together with the generic type identifier. The size of the + /// data retrieved from the dereferenced address is specified by the + /// operand, whose value is a 1-byte unsigned integral constant. The data + /// retrieved is zero-extended to the size of an address on the target machine + /// before being pushed onto the expression stack. + case xderefSize(UInt8) + /// Pops the top two stack entries, treats them as an address and an address + /// space identifier, and pushes the value retrieved. + /// The size of the data retrieved from the dereferenced address is specified + /// by the first operand, whose value is a 1-byte unsigned integral constant. + /// The data retrieved is zero-extended to the size of an address on the + /// target machine before being pushed onto the expression stack. The second + /// operand is an unsigned little-endian base-128 integer that represents the + /// offset of a debugging information entry in the current compilation unit, + /// which must have base type that provides the type of the data pushed. + case xderefType(UInt8, UInt64) + + /// Pushes the address of the object currently being evaluated as part of + /// evaluationo of a user-presented expression. The object may correspond + /// to an indepdendent variable deescribed by its own debugging information + /// entry or it may be a component of an array, structure, or class whose + /// address has been dynamically determined by an earlier step during + /// user expression evaluation. + case pushObjectAddress + /// Pops a value from the stack, which must have an integral type identifier, + /// translates this value into an address in the thread-local storage for a + /// thread, and pushes the addreess onto the stack together with the generic + /// type identifier. The meaning of the value on the top of the stack prior + /// to this operation is defined by the run-time environment. If the run-time + /// environment supports multiple thread-local storage blocks for a single + /// thread, then the block corresponding to the executable or shared library + /// containing this DWARF expreession is used. + case formTLSAddress + /// Pushes the value of the Canonical Frame Address (CFA), obtained from the + /// Call Frame Information. + case callFrameCFA + + // MARK: Arithmetic and Logical Operations + + /// Pops the top stack entry, interprets it as a signed value and pushes its + /// absolute value. If the absolute value cannot be represented, the result + /// is undefined. + case abs + /// Pops the top two stack values, performs a bitwise and operation on the + /// two, and pushes the result. + case and + /// Pops the top two stack values, divides the former second entry by the + /// former top of the stack using signed division, and pushes the result. + case div + /// Pops the top two stack values, subtracts the former second entry by the + /// former top of the stack, and pushes the result. + case minus + /// Pops the top two stack values, performs a modulo operation on the + /// two, and pushes the result. + case mod + /// Pops the top two stack values, multiplies the former second entry by the + /// former top of the stack, and pushes the result. + case mul + /// Pops the top stack entry, interprets it as a signed value, and pushes its + /// negation. If the negation cannot be represented, the result is undefined. + case neg + /// Pops the top stack entry, and pushes its bitwise complement. + case not + /// Pops the top two stack entries, performs a bitwise or operation on the + /// two, and pushes the result. + case or + /// Pops the top two stack entries, adds them together, and pushes the result. + case plus + /// Pops the top stack entry, adds it to the unsigned little-endian base-128 + /// constant operand interpreted as the same type as the operand popped from + /// the top of the stack and pushes the result. + case plus_uconst(UInt64) + /// Pops the top twoo stack entries, shifts the former second entry left + /// (filling with zero bits) by the number of bits specified by the former + /// top of the stack, and pushes the result. + case shl + /// Pops the top two stack entries, shifts the former second entry right + /// logically (filling with zero bits) by the number of bits specified by + /// the former top of the stack, and pushes the result. + case shr + /// Pops the top two stack entries, shifts the former second entry right + /// arithmetically (divides the magnitude by 2, keeps the same sign for the + /// result) by the number of bits specified by the former top of the stack, + /// and pushes the result. + case shra + /// Pops the top two stack entries, performs a bitwise exclusive-or operation + /// on the two, and pushes the result. + case xor + + // MARK: Control Flow Operations + + /// Pops the top two stack values, which must have the same type, either + /// the base type or the generic type, compares them using the `=` relational + /// operator, and pushes the constant 1 onto the stack if the result is + /// true, else pushes the constnat value 0 if the result is false. + case eq + /// Pops the top two stack values, which must have the same type, either + /// the base type or the generic type, compares them using the `>=` relational + /// operator, and pushes the constant 1 onto the stack if the result is + /// true, else pushes the constnat value 0 if the result is false. + case ge + /// Pops the top two stack values, which must have the same type, either + /// the base type or the generic type, compares them using the `>` relational + /// operator, and pushes the constant 1 onto the stack if the result is + /// true, else pushes the constnat value 0 if the result is false. + case gt + /// Pops the top two stack values, which must have the same type, either + /// the base type or the generic type, compares them using the `<=` relational + /// operator, and pushes the constant 1 onto the stack if the result is + /// true, else pushes the constnat value 0 if the result is false. + case le + /// Pops the top two stack values, which must have the same type, either + /// the base type or the generic type, compares them using the `<` relational + /// operator, and pushes the constant 1 onto the stack if the result is + /// true, else pushes the constnat value 0 if the result is false. + case lt + /// Pops the top two stack values, which must have the same type, either + /// the base type or the generic type, compares them using the `!=` relational + /// operator, and pushes the constant 1 onto the stack if the result is + /// true, else pushes the constnat value 0 if the result is false. + case ne + /// Unconditionally branches forward or backward by the number of bytes + /// specified in its operand. + case skip(Int16) + /// Conditionally branches forward or backward by the number of bytes + /// specified in its operand according to the value at the top of the stack. + /// The top of the stack is popped, and if it is non-zero then the branch is + /// performed. + case bra(Int16) + + /// Performs a DWARF procedure call during the evaluation of a DWARF + /// expression or location description. The operand is the 2-byte unsigned + /// offset of a debugging information entry in the current compilation unit. + /// + /// For references from one executable or shared object file to another, + /// the relocation must be performed by the consumer. + /// + /// This operation transfers control of DWARF expression evaluation to the + /// `DW_AT_location` attribute of the referenced debugging information entry. + /// If there is no such attribute, then there is no effect. Execution + /// returns to the point following the call when the end of the attribute + /// is reached. + case call2(UInt16) + /// Performs a DWARF procedure call during the evaluation of a DWARF + /// expression or location description. The operand is the 4-byte unsigned + /// offset of a debugging information entry in the current compilation unit. + /// + /// For references from one executable or shared object file to another, + /// the relocation must be performed by the consumer. + /// + /// This operation transfers control of DWARF expression evaluation to the + /// `DW_AT_location` attribute of the referenced debugging information entry. + /// If there is no such attribute, then there is no effect. Execution + /// returns to the point following the call when the end of the attribute + /// is reached. + case call4(UInt32) + /// Performs a DWARF procedure call during the evaluation of a DWARF + /// expression or location description. The operand is used as the offset of + /// a debugging information entry in a `.debug_info` section which may be + /// contained in an executable or shared object file rather than that + /// containing the operator. + /// + /// For references from one executable or shared object file to another, + /// the relocation must be performed by the consumer. + /// + /// This operation transfers control of DWARF expression evaluation to the + /// `DW_AT_location` attribute of the referenced debugging information entry. + /// If there is no such attribute, then there is no effect. Execution + /// returns to the point following the call when the end of the attribute + /// is reached. + case callRef(UInt64) + + // MARK: Type Conversions + + /// Pops the top stack entry, converts it to a different type, then pushes the + /// result. + /// + /// The operand is an unsigned little-endian base-128 integer that represents + /// the offset of a debugging information entry in the current compilation + /// unit, or value 0 which represents the generic type. If the operand is + /// non-zero, the referenced entry must be a base type entry that provides the + /// type to which the value is converted. + case convert(UInt64) + /// Pops the top stack entry, reinterprets the bits in its value as a value of + /// a different type, then pushes the result. + /// + /// The operand is an unsigned little-endian base-128 integer that represents + /// the offset of a debugging information entry in the current compilation + /// unit, or value 0 which represents the generic type. If the operand is + /// non-zero, the referenced entry must be a base type entry that provides the + /// type to which the value is converted. + case reinterpret(UInt64) + + + // MARK: Special Operations + + /// This operation has no effect on the location stack or any of its values. + case nop + /// Pushes the value that the described location held upon entering the + /// current subprogram. The first operand is an unsigned little-endian + /// base-128 number expressing the length of the second operand in bytes. The + /// second operand is a block containing a DWARF expression or a register + /// location description. + indirect case entryValue(UInt64, DWARFExpression) + + // MARK: Location Descriptions + + /// Encodes the name of the register numbered 0. + case reg0 + /// Encodes the name of the register numbered 1. + case reg1 + /// Encodes the name of the register numbered 2. + case reg2 + /// Encodes the name of the register numbered 3. + case reg3 + /// Encodes the name of the register numbered 4. + case reg4 + /// Encodes the name of the register numbered 5. + case reg5 + /// Encodes the name of the register numbered 6. + case reg6 + /// Encodes the name of the register numbered 7. + case reg7 + /// Encodes the name of the register numbered 8. + case reg8 + /// Encodes the name of the register numbered 9. + case reg9 + /// Encodes the name of the register numbered 10. + case reg10 + /// Encodes the name of the register numbered 11. + case reg11 + /// Encodes the name of the register numbered 12. + case reg12 + /// Encodes the name of the register numbered 13. + case reg13 + /// Encodes the name of the register numbered 14. + case reg14 + /// Encodes the name of the register numbered 15. + case reg15 + /// Encodes the name of the register numbered 16. + case reg16 + /// Encodes the name of the register numbered 17. + case reg17 + /// Encodes the name of the register numbered 18. + case reg18 + /// Encodes the name of the register numbered 19. + case reg19 + /// Encodes the name of the register numbered 20. + case reg20 + /// Encodes the name of the register numbered 21. + case reg21 + /// Encodes the name of the register numbered 22. + case reg22 + /// Encodes the name of the register numbered 23. + case reg23 + /// Encodes the name of the register numbered 24. + case reg24 + /// Encodes the name of the register numbered 25. + case reg25 + /// Encodes the name of the register numbered 26. + case reg26 + /// Encodes the name of the register numbered 27. + case reg27 + /// Encodes the name of the register numbered 28. + case reg28 + /// Encodes the name of the register numbered 29. + case reg29 + /// Encodes the name of the register numbered 30. + case reg30 + /// Encodes the name of the register numbered 31. + case reg31 + + /// Contains a single unsigned little-endian base-128 literal operand that + /// encodes the name of a register. + case regx(UInt64) + + // MARK: Implicit Location Descriptionos + + /// Specifies an immediate value using two operands: an unsigned little-endian + /// base-128 length, followed by a sequence of bytes of the given length that + /// contain the value. + case implicitValue(UInt64, [UInt8]) + + /// Specifies that the object does not exist in memory, but its value is + /// nonetheless known and is at the top of the DWARF expression stack. In + /// this form of location description, the DWARF expression represents the + /// actual value of the object, rather than its location. + /// + /// `stackValue` acts as an expression terminator. + case stackValue + + // MARK: Composite Location Descriptions + + /// Takes a single operand in little-endian base-128 form. This operand + /// describes the size in bytes of the piece of the object referenced by the + /// preceding simple location description. If the piece is located in a + /// register, but does not occupy the entire register, the placement of + /// the piece within that register is defined by the ABI. + case piece(UInt64) + /// Takes two operands, an unsigned little-endian base-128 form number that + /// gives the size in bits of the piece. The second is an unsigned little- + /// endian base-128 number that gives the offset in bits from the location + /// defined by the preceding DWARF location description. + /// + /// `bitPiece` is used instead of `piece` when the piece to be assembled into + /// a value or assigned to is not byte-sized or is not at the start of a + /// register or addressable unit of memory. + /// + /// Interpretation of the offset depends on the location description. If the + /// location description is empty, the offset doesn’t matter and the + /// `bitPiece` operation describes a piece consisting of the given number of + /// bits whose values are undefined. If the location is a register, the offset + /// is from the least significant bit end of the register. If the location is + /// a memory address, the `bitPiece` operation describes a sequence of bits + /// relative to the location whose address is on the top of the DWARF stack + /// using the bit numbering and direction conventions that are appropriate to + /// the current language on the target system. If the location is any implicit + /// value or stack value, the `bitPiece` operation describes a sequence of + /// bits using the least significant bits of that value. + case bitPiece(UInt64, UInt64) + + /// Specifies that the object is a pointer that cannot be represented as a + /// real pointer, even though the value it would point to can be described. + /// + /// In this form of location description, the DWARF expression refers to a + /// debugging information entry that represents the actual value of the object + /// to which the pointer would point. Thus, a consumer of the debug + /// information would be able to show the value of the dereferenced pointer, + /// even when it cannot show the value of the pointer itself. + /// + /// The first operand is used as the offset of a debugging information entry + /// in a `.debug_info` section, which may be contained in an executable or + /// shared object file other than that containing the operator. + /// + /// For references from one executable or shared object file to another, the + /// relocation must be performed by the consumer. + case implicitPointer(UInt64, Int64) +} + +extension DWARFExpression { + var rawValue: [UInt64] { + switch self { + case let .addr(val): + return [ 0x03, val ] + case .deref: + return [ 0x06 ] + case let .const1u(val): + return [ 0x08, UInt64(val) ] + case let .const1s(val): + return [ 0x09, UInt64(bitPattern: Int64(val)) ] + case let .const2u(val): + return [ 0x0a, UInt64(val) ] + case let .const2s(val): + return [ 0x0b, UInt64(bitPattern: Int64(val)) ] + case let .const4u(val): + return [ 0x0c, UInt64(val) ] + case let .const4s(val): + return [ 0x0d, UInt64(bitPattern: Int64(val)) ] + case let .const8u(val): + return [ 0x0e, val ] + case let .const8s(val): + return [ 0x0f, UInt64(bitPattern: Int64(val)) ] + case let .constu(val): + return [ 0x10, val ] + case let .consts(val): + return [ 0x11, UInt64(bitPattern: val) ] + case .dup: + return [ 0x12 ] + case .drop: + return [ 0x13 ] + case .over: + return [ 0x14 ] + case let .pick(val): + return [ 0x15, UInt64(val) ] + case .swap: + return [ 0x16 ] + case .rot: + return [ 0x17 ] + case .xderef: + return [ 0x18 ] + case .abs: + return [ 0x19 ] + case .and: + return [ 0x1a ] + case .div: + return [ 0x1b ] + case .minus: + return [ 0x1c ] + case .mod: + return [ 0x1d ] + case .mul: + return [ 0x1e ] + case .neg: + return [ 0x1f ] + case .not: + return [ 0x20 ] + case .or: + return [ 0x21 ] + case .plus: + return [ 0x22 ] + case let .plus_uconst(val): + return [ 0x23, val ] + case .shl: + return [ 0x24 ] + case .shr: + return [ 0x25 ] + case .shra: + return [ 0x26 ] + case .xor: + return [ 0x27 ] + case .skip: + return [ 0x2f ] + case .bra: + return [ 0x28 ] + case .eq: + return [ 0x29 ] + case .ge: + return [ 0x2a ] + case .gt: + return [ 0x2b ] + case .le: + return [ 0x2c ] + case .lt: + return [ 0x2d ] + case .ne: + return [ 0x2e ] + case .lit0: + return [ 0x30 ] + case .lit1: + return [ 0x31 ] + case .lit2: + return [ 0x32 ] + case .lit3: + return [ 0x33 ] + case .lit4: + return [ 0x34 ] + case .lit5: + return [ 0x35 ] + case .lit6: + return [ 0x36 ] + case .lit7: + return [ 0x37 ] + case .lit8: + return [ 0x38 ] + case .lit9: + return [ 0x39 ] + case .lit10: + return [ 0x3a ] + case .lit11: + return [ 0x3b ] + case .lit12: + return [ 0x3c ] + case .lit13: + return [ 0x3d ] + case .lit14: + return [ 0x3e ] + case .lit15: + return [ 0x3f ] + case .lit16: + return [ 0x40 ] + case .lit17: + return [ 0x41 ] + case .lit18: + return [ 0x42 ] + case .lit19: + return [ 0x43 ] + case .lit20: + return [ 0x44 ] + case .lit21: + return [ 0x45 ] + case .lit22: + return [ 0x46 ] + case .lit23: + return [ 0x47 ] + case .lit24: + return [ 0x48 ] + case .lit25: + return [ 0x49 ] + case .lit26: + return [ 0x4a ] + case .lit27: + return [ 0x4b ] + case .lit28: + return [ 0x4c ] + case .lit29: + return [ 0x4d ] + case .lit30: + return [ 0x4e ] + case .lit31: + return [ 0x4f ] + case .reg0: + return [ 0x50 ] + case .reg1: + return [ 0x51 ] + case .reg2: + return [ 0x52 ] + case .reg3: + return [ 0x53 ] + case .reg4: + return [ 0x54 ] + case .reg5: + return [ 0x55 ] + case .reg6: + return [ 0x56 ] + case .reg7: + return [ 0x57 ] + case .reg8: + return [ 0x58 ] + case .reg9: + return [ 0x59 ] + case .reg10: + return [ 0x5a ] + case .reg11: + return [ 0x5b ] + case .reg12: + return [ 0x5c ] + case .reg13: + return [ 0x5d ] + case .reg14: + return [ 0x5e ] + case .reg15: + return [ 0x5f ] + case .reg16: + return [ 0x60 ] + case .reg17: + return [ 0x61 ] + case .reg18: + return [ 0x62 ] + case .reg19: + return [ 0x63 ] + case .reg20: + return [ 0x64 ] + case .reg21: + return [ 0x65 ] + case .reg22: + return [ 0x66 ] + case .reg23: + return [ 0x67 ] + case .reg24: + return [ 0x68 ] + case .reg25: + return [ 0x69 ] + case .reg26: + return [ 0x6a ] + case .reg27: + return [ 0x6b ] + case .reg28: + return [ 0x6c ] + case .reg29: + return [ 0x6d ] + case .reg30: + return [ 0x6e ] + case .reg31: + return [ 0x6f ] + case let .breg0(val): + return [ 0x70, UInt64(bitPattern: val)] + case let .breg1(val): + return [ 0x71, UInt64(bitPattern: val) ] + case let .breg2(val): + return [ 0x72, UInt64(bitPattern: val) ] + case let .breg3(val): + return [ 0x73, UInt64(bitPattern: val) ] + case let .breg4(val): + return [ 0x74, UInt64(bitPattern: val) ] + case let .breg5(val): + return [ 0x75, UInt64(bitPattern: val) ] + case let .breg6(val): + return [ 0x76, UInt64(bitPattern: val) ] + case let .breg7(val): + return [ 0x77, UInt64(bitPattern: val) ] + case let .breg8(val): + return [ 0x78, UInt64(bitPattern: val) ] + case let .breg9(val): + return [ 0x79, UInt64(bitPattern: val) ] + case let .breg10(val): + return [ 0x7a, UInt64(bitPattern: val) ] + case let .breg11(val): + return [ 0x7b, UInt64(bitPattern: val) ] + case let .breg12(val): + return [ 0x7c, UInt64(bitPattern: val) ] + case let .breg13(val): + return [ 0x7d, UInt64(bitPattern: val) ] + case let .breg14(val): + return [ 0x7e, UInt64(bitPattern: val) ] + case let .breg15(val): + return [ 0x7f, UInt64(bitPattern: val) ] + case let .breg16(val): + return [ 0x80, UInt64(bitPattern: val) ] + case let .breg17(val): + return [ 0x81, UInt64(bitPattern: val) ] + case let .breg18(val): + return [ 0x82, UInt64(bitPattern: val) ] + case let .breg19(val): + return [ 0x83, UInt64(bitPattern: val) ] + case let .breg20(val): + return [ 0x84, UInt64(bitPattern: val) ] + case let .breg21(val): + return [ 0x85, UInt64(bitPattern: val) ] + case let .breg22(val): + return [ 0x86, UInt64(bitPattern: val) ] + case let .breg23(val): + return [ 0x87, UInt64(bitPattern: val) ] + case let .breg24(val): + return [ 0x88, UInt64(bitPattern: val) ] + case let .breg25(val): + return [ 0x89, UInt64(bitPattern: val) ] + case let .breg26(val): + return [ 0x8a, UInt64(bitPattern: val) ] + case let .breg27(val): + return [ 0x8b, UInt64(bitPattern: val) ] + case let .breg28(val): + return [ 0x8c, UInt64(bitPattern: val) ] + case let .breg29(val): + return [ 0x8d, UInt64(bitPattern: val) ] + case let .breg30(val): + return [ 0x8e, UInt64(bitPattern: val) ] + case let .breg31(val): + return [ 0x8f, UInt64(bitPattern: val) ] + case let .regx(val): + return [ 0x90, val ] + case let .fbreg(val): + return [ 0x91, UInt64(bitPattern: val) ] + case let .bregx(val1, val2): + return [ 0x92, val1 , UInt64(bitPattern: val2) ] + case let .piece(val): + return [ 0x93, val ] + case let .derefSize(val): + return [ 0x94, UInt64(val) ] + case let .xderefSize(val): + return [ 0x95, UInt64(val) ] + case .nop: + return [ 0x96 ] + case .pushObjectAddress: + return [ 0x97 ] + case let .call2(val): + return [ 0x98, UInt64(val) ] + case let .call4(val): + return [ 0x99, UInt64(val) ] + case let .callRef(val): + return [ 0x9a, val ] + case .formTLSAddress: + return [ 0x9b ] + case .callFrameCFA: + return [ 0x9c ] + case let .bitPiece(val1, val2): + return [ 0x9d, val1, val2 ] + case let .implicitValue(val, bytes): + return [ 0x9e, val ] + packBytes(bytes) + case .stackValue: + return [ 0x9f ] + case let .implicitPointer(val1, val2): + return [ 0xa0, val1, UInt64(bitPattern: val2) ] + case let .addrx(val): + return [ 0xa1, val ] + case let .constx(val): + return [ 0xa2, val ] + case let .entryValue(val1, val2): + return [ 0xa3, val1 ] + val2.rawValue + case let .constType(ate, n, bytes): + assert(Int(n) == bytes.count) + return [ 0xa4, UInt64(ate.llvm), UInt64(n) ] + packBytes(bytes) + case let .regvalType(reg, ate): + return [ 0xa5, reg, UInt64(ate.llvm) ] + case let .derefType(val, ty): + return [ 0xa6, UInt64(val), ty ] + case let .xderefType(val, ty): + return [ 0xa7, UInt64(val), ty ] + case let .convert(ty): + return [ 0xa7, ty ] + case let .reinterpret(ty): + return [ 0xa7, ty ] + } + } +} + +private func packBytes(_ bytes: [UInt8]) -> [UInt64] { + guard !bytes.isEmpty else { + return [] + } + + var res = [UInt64]() + res.reserveCapacity(bytes.count/MemoryLayout.size) + var accum: UInt64 = 0 + for (idx, val) in bytes.enumerated() { + // If we've packed all the way through the accumulator, append it and + // start afresh. + if idx != 0 && idx % MemoryLayout.size == 0 { + res.append(accum) + accum = 0 + } + + accum <<= MemoryLayout.size + accum |= UInt64(val) + } + + // Pack on the straggler if we're not packing a perfect multiple. + if bytes.count % MemoryLayout.size != 0 { + res.append(accum) + } + return res +} diff --git a/Sources/LLVM/FloatType.swift b/Sources/LLVM/FloatType.swift index 01479384..c70fced5 100644 --- a/Sources/LLVM/FloatType.swift +++ b/Sources/LLVM/FloatType.swift @@ -22,6 +22,7 @@ public struct FloatType: IRType { self.context = context } + /// Enumerates the bitwidth and kind of supported floating point types. public enum Kind { /// 16-bit floating point value case half @@ -84,3 +85,9 @@ public struct FloatType: IRType { } } } + +extension FloatType: Equatable { + public static func == (lhs: FloatType, rhs: FloatType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() + } +} diff --git a/Sources/LLVM/Function+Attributes.swift b/Sources/LLVM/Function+Attributes.swift new file mode 100644 index 00000000..9ea922fa --- /dev/null +++ b/Sources/LLVM/Function+Attributes.swift @@ -0,0 +1,382 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +/// Enumerates the kinds of attributes of LLVM functions and function parameters. +public enum AttributeKind: String { + /// This attribute indicates that, when emitting the prologue and epilogue, + /// the backend should forcibly align the stack pointer. + case alignstack + /// This attribute indicates that the annotated function will always return + /// at least a given number of bytes (or null). + case allocsize + /// This attribute indicates that the inliner should attempt to inline this + /// function into callers whenever possible, ignoring any active inlining + /// size threshold for this caller. + case alwaysinline + /// This indicates that the callee function at a call site should be + /// recognized as a built-in function, even though the function’s declaration + /// uses the nobuiltin attribute + case builtin + /// This attribute indicates that this function is rarely called. + case cold + /// In some parallel execution models, there exist operations that cannot be + /// made control-dependent on any additional values. + case convergent + /// This attribute indicates that the function may only access memory that is + /// not accessible by the module being compiled. + case inaccessiblememonly + /// This attribute indicates that the function may only access memory that is + /// either not accessible by the module being compiled, or is pointed to by + /// its pointer arguments. + case inaccessiblememOrArgmemonly = "inaccessiblemem_or_argmemonly" + /// This attribute indicates that the source code contained a hint that inlin + /// inlining this function is desirable (such as the “inline” keyword in + /// C/C++). + case inlinehint + /// This attribute indicates that the function should be added to a + /// jump-instruction table at code-generation time, and that all + /// address-taken references to this function should be replaced with a + /// reference to the appropriate jump-instruction-table function pointer. + case jumptable + /// This attribute suggests that optimization passes and code generator + /// passes make choices that keep the code size of this function as small as + /// possible and perform optimizations that may sacrifice runtime performance + /// in order to minimize the size of the generated code. + case minsize + /// This attribute disables prologue / epilogue emission for the function. + case naked + /// When this attribute is set to true, the jump tables and lookup tables + /// that can be generated from a switch case lowering are disabled. + case noJumpTables = "no-jump-tables" + /// This indicates that the callee function at a call site is not recognized + /// as a built-in function. + case nobuiltin + /// This attribute indicates that calls to the function cannot be duplicated. + case noduplicate + /// This attributes disables implicit floating point instructions. + case noimplicitfloat + /// This attribute indicates that the inliner should never inline this + /// function in any situation. + case noinline + /// This attribute suppresses lazy symbol binding for the function. + case nonlazybind + /// This attribute indicates that the code generator should not use a red + /// zone, even if the target-specific ABI normally permits it. + case noredzone + /// This function attribute indicates that the function never returns + /// normally. + case noreturn + /// This function attribute indicates that the function does not call itself + /// either directly or indirectly down any possible call path. + case norecurse + /// This function attribute indicates that the function never raises an + /// exception. + case nounwind + /// This function attribute indicates that most optimization passes will skip + /// this function, with the exception of interprocedural optimization passes. + case optnone + /// This attribute suggests that optimization passes and code generator + /// passes make choices that keep the code size of this function low, and + /// otherwise do optimizations specifically to reduce code size as long as + /// they do not significantly impact runtime performance. + case optsize + /// This attribute indicates that the function computes its result (or + /// decides to unwind an exception) based strictly on its arguments, without + /// dereferencing any pointer arguments or otherwise accessing any mutable + /// state (e.g. memory, control registers, etc) visible to caller functions. + case readnone + /// This attribute indicates that the function does not write through any + /// pointer arguments (including byval arguments) or otherwise modify any + /// state (e.g. memory, control registers, etc) visible to caller functions. + case readonly + /// This attribute indicates that the function may write to but does not read + /// read from memory. + case writeonly + /// This attribute indicates that the only memory accesses inside function + /// are loads and stores from objects pointed to by its pointer-typed + /// arguments, with arbitrary offsets. + case argmemonly + /// This attribute indicates that this function can return twice. + case returnsTwice = "returns_twice" + /// This attribute indicates that SafeStack protection is enabled for this + /// function. + case safestack + /// This attribute indicates that AddressSanitizer checks (dynamic address + /// safety analysis) are enabled for this function. + case sanitizeAddress = "sanitize_address" + /// This attribute indicates that MemorySanitizer checks (dynamic detection + /// of accesses to uninitialized memory) are enabled for this function. + case sanitizeMemory = "sanitize_memory" + /// This attribute indicates that ThreadSanitizer checks (dynamic thread + /// safety analysis) are enabled for this function. + case sanitizeThread = "sanitize_thread" + /// This attribute indicates that HWAddressSanitizer checks (dynamic address + /// safety analysis based on tagged pointers) are enabled for this function. + case sanitizeHWAddress = "sanitize_hwaddress" + /// This function attribute indicates that the function does not have any + /// effects besides calculating its result and does not have undefined + /// behavior. + case speculatable + /// This attribute indicates that the function should emit a stack smashing + /// protector. + case ssp + /// This attribute indicates that the function should always emit a stack + /// smashing protector + case sspreq + /// This attribute indicates that the function should emit a stack smashing + /// protector. + case sspstrong + /// This attribute indicates that the function was called from a scope that + /// requires strict floating point semantics. + case strictfp + /// This attribute indicates that the ABI being targeted requires that an + /// unwind table entry be produced for this function even if we can show + /// that no exceptions passes by it. + case uwtable + /// This indicates to the code generator that the parameter or return value + /// should be zero-extended to the extent required by the target’s ABI by the + /// caller (for a parameter) or the callee (for a return value). + case zeroext + /// This indicates to the code generator that the parameter or return value + /// should be sign-extended to the extent required by the target’s ABI (which + /// is usually 32-bits) by the caller (for a parameter) or the callee (for a + /// return value). + case signext + /// This indicates that this parameter or return value should be treated in a + /// special target-dependent fashion while emitting code for a function call + /// or return. + case inreg + /// This indicates that the pointer parameter should really be passed by + /// value to the function. + case byval + /// The inalloca argument attribute allows the caller to take the address of + /// outgoing stack arguments + case inalloca + /// This indicates that the pointer parameter specifies the address of a + /// structure that is the return value of the function in the source program. + case sret + /// This indicates that the pointer value may be assumed by the optimizer to + /// have the specified alignment. + case align + /// This indicates that objects accessed via pointer values based on the + /// argument or return value are not also accessed, during the execution of + /// the function, via pointer values not based on the argument or return + /// value. + /// + /// The `noalias` attribute may appear in one of two location: on arguments + /// types or on return types. On argument types, `noalias` acts like the + /// `restrict` keyword in C and C++ and implies that no other pointer value + /// points to this object. On return types, `noalias` implies that the + /// returned pointer is not aliased by any other pointer in the program. + /// + /// Practically, this allows LLVM to reorder accesses to this memory. + case noalias + /// This indicates that the callee does not make any copies of the pointer + /// that outlive the callee itself. + case nocapture + /// This indicates that the pointer parameter can be excised using the + /// trampoline intrinsics. + case nest + /// This indicates that the function always returns the argument as its + /// return value. + case returned + /// This indicates that the parameter or return pointer is not null. + case nonnull + /// This indicates that the parameter or return pointer is dereferenceable. + case dereferenceable + /// This indicates that the parameter or return value isn’t both non-null and + /// non-dereferenceable (up to `n` bytes) at the same time. + case dereferenceableOrNull = "dereferenceable_or_null" + /// This indicates that the parameter is the self/context parameter. + case swiftself + /// This attribute is motivated to model and optimize Swift error handling. + case swifterror + + /// ID of the attribute. + internal var id: UInt32 { + return LLVMGetEnumAttributeKindForName(rawValue, rawValue.count) + } +} + +/// Represents the possible indices of function attributes. +public enum AttributeIndex: ExpressibleByIntegerLiteral, RawRepresentable { + /// Represents the function itself. + case function + /// Represents the function's return value. + case returnValue + /// Represents the function's i-th argument. + case argument(Int) + + public init(integerLiteral value: UInt32) { + switch value { + case ~0: self = .function + case 0: self = .returnValue + default: self = .argument(Int(value) - 1) + } + } + + public init?(rawValue: RawValue) { + self.init(integerLiteral: rawValue) + } + + public var rawValue: UInt32 { + switch self { + case .function: return ~0 + case .returnValue: return 0 + case .argument(let i): return UInt32(i) + 1 + } + } +} + +/// An LLVM attribute. +/// +/// Functions, return types and each parameter may have a set of attributes +/// associated with them. Such attributes are used to communicate additional +/// information about a function. Attributes are considered to be part of the +/// function, but not of the function type. +public protocol Attribute { + /// Retrieves the underlying LLVM attribute reference object. + func asLLVM() -> LLVMAttributeRef +} + +/// An "enum" (a.k.a. target-independent) attribute. +public struct EnumAttribute: Attribute { + internal let llvm: LLVMAttributeRef + internal init(llvm: LLVMAttributeRef) { + self.llvm = llvm + } + + /// The kind ID of the attribute. + internal var kindID: UInt32 { + return LLVMGetEnumAttributeKind(llvm) + } + + /// The value of the attribute. + public var value: UInt64 { + return LLVMGetEnumAttributeValue(llvm) + } + + /// Retrieves the underlying LLVM attribute object. + public func asLLVM() -> LLVMAttributeRef { + return llvm + } +} + +/// A "string" (a.k.a. target-dependent) attribute. +public struct StringAttribute: Attribute { + internal let llvm: LLVMAttributeRef + internal init(llvm: LLVMAttributeRef) { + self.llvm = llvm + } + + /// The name of the attribute. + public var name: String { + var length: UInt32 = 0 + let cstring = LLVMGetStringAttributeKind(llvm, &length) + return String.init(cString: cstring!) + } + + /// The value of the attribute. + public var value: String { + var length: UInt32 = 0 + let cstring = LLVMGetStringAttributeValue(llvm, &length) + return String.init(cString: cstring!) + } + + /// Retrieves the underlying LLVM attribute object. + public func asLLVM() -> LLVMAttributeRef { + return llvm + } +} + +extension Function { + /// Adds an enum attribute to the function, its return value or one of its + /// parameters. + /// + /// - parameter attrKind: The kind of the attribute to add. + /// - parameter value: The optional value of the attribute. + /// - parameter index: The index representing the function, its return value + /// or one of its parameters. + @discardableResult + public func addAttribute(_ attrKind: AttributeKind, value: UInt64 = 0, to index: AttributeIndex) -> EnumAttribute { + let ctx = LLVMGetModuleContext(LLVMGetGlobalParent(llvm)) + let attrRef = LLVMCreateEnumAttribute(ctx, attrKind.id, value) + LLVMAddAttributeAtIndex(llvm, index.rawValue, attrRef) + return EnumAttribute(llvm: attrRef!) + } + + /// Adds a string attribute to the function, its return value or one of its + /// parameters. + /// + /// - parameter name: The name of the attribute to add. + /// - parameter value: The optional value of the attribute. + /// - parameter index: The index representing the function, its return value + /// or one of its parameters. + @discardableResult + public func addAttribute(_ name: String, value: String = "", to index: AttributeIndex) -> StringAttribute { + let ctx = LLVMGetModuleContext(LLVMGetGlobalParent(llvm)) + let attrRef = name.withCString { cname -> LLVMAttributeRef? in + return value.withCString { cvalue in + return LLVMCreateStringAttribute(ctx, cname, UInt32(name.count), cvalue, UInt32(value.count)) + } + } + LLVMAddAttributeAtIndex(llvm, index.rawValue, attrRef) + return StringAttribute(llvm: attrRef!) + } + + /// Removes an attribute from the function, its return value or one of its + /// parameters. + /// + /// - parameter attr: The attribute to remove. + /// - parameter index: The index representing the function, its return value + /// or one of its parameters. + public func removeAttribute(_ attr: Attribute, from index: AttributeIndex) { + switch attr { + case let enumAttr as EnumAttribute: + LLVMRemoveEnumAttributeAtIndex(llvm, index.rawValue, enumAttr.kindID) + case let stringAttr as StringAttribute: + var length: UInt32 = 0 + let cstring = LLVMGetStringAttributeKind(stringAttr.llvm, &length) + LLVMRemoveStringAttributeAtIndex(llvm, index.rawValue, cstring, length) + default: + fatalError("unexpected attribute type") + } + } + + /// Removes an enum attribute from the function, its return value or one of + /// its parameters. + /// + /// - parameter attr: The kind of the attribute to remove. + /// - parameter index: The index representing the function, its return value + /// or one of its parameters. + public func removeAttribute(_ attrKind: AttributeKind, from index: AttributeIndex) { + LLVMRemoveEnumAttributeAtIndex(llvm, index.rawValue, attrKind.id) + } + + /// Removes a string attribute from the function, its return value or one of + /// its parameters. + /// + /// - parameter name: The name of the attribute to remove. + /// - parameter index: The index representing the function, its return value + /// or one of its parameters. + public func removeAttribute(_ name: String, from index: AttributeIndex) { + name.withCString { + LLVMRemoveStringAttributeAtIndex(llvm, index.rawValue, $0, UInt32(name.count)) + } + } + + /// Gets the attributes of the function, its return value or its parameters. + public func attributes(at index: AttributeIndex) -> [Attribute] { + let attrCount = LLVMGetAttributeCountAtIndex(llvm, index.rawValue) + var attrRefs: [LLVMAttributeRef?] = Array(repeating: nil, count: Int(attrCount)) + LLVMGetAttributesAtIndex(llvm, index.rawValue, &attrRefs) + return attrRefs.map { attrRef -> Attribute in + if LLVMIsEnumAttribute(attrRef) != 0 { + return EnumAttribute(llvm: attrRef!) + } else { + return StringAttribute(llvm: attrRef!) + } + } + } +} diff --git a/Sources/LLVM/Function.swift b/Sources/LLVM/Function.swift index b9440252..5da2e97e 100644 --- a/Sources/LLVM/Function.swift +++ b/Sources/LLVM/Function.swift @@ -1,61 +1,109 @@ #if SWIFT_PACKAGE import cllvm +import llvmshims #endif -/// Enumerates the calling conventions supported by LLVM. -/// -/// The raw values of this enumeration *must* match those in -/// [llvm-c/Core.h](https://github.com/llvm-mirror/llvm/blob/master/include/llvm-c/Core.h) -public enum CallingConvention: UInt32 { - /// The default LLVM calling convention, compatible with C. - case c = 0 - /// This calling convention attempts to make calls as fast as possible - /// (e.g. by passing things in registers). - case fast = 8 - /// This calling convention attempts to make code in the caller as efficient - /// as possible under the assumption that the call is not commonly executed. - /// As such, these calls often preserve all registers so that the call does - /// not break any live ranges in the caller side. - case cold = 9 - /// Calling convention for stack based JavaScript calls. - case webKitJS = 12 - /// Calling convention for dynamic register based calls - /// (e.g. stackmap and patchpoint intrinsics). - case anyReg = 13 - /// The calling conventions mostly used by the Win32 API. - /// - /// It is basically the same as the C convention with the difference in that - /// the callee is responsible for popping the arguments from the stack. - case x86Stdcall = 64 - /// "Fast" analog of `x86Stdcall`. - /// - /// Passes first two arguments in ECX:EDX registers, others via the stack. - /// The callee is responsible for stack cleaning. - case x86Fastcall = 65 -} - /// A `Function` represents a named function body in LLVM IR source. Functions /// in LLVM IR encapsulate a list of parameters and a sequence of basic blocks /// and provide a way to append to that sequence to build out its body. +/// +/// A LLVM function definition contains a list of basic blocks, starting with +/// a privileged first block called the "entry block". After the entry blocks' +/// terminating instruction come zero or more other basic blocks. The path the +/// flow of control can potentially take, from each block to its terminator +/// and on to other blocks, forms the "Control Flow Graph" (CFG) for the +/// function. The nodes of the CFG are the basic blocks, and the edges are +/// directed from the terminator instruction of one block to any number of +/// potential target blocks. +/// +/// Additional basic blocks may be created and appended to the function at +/// any time. +/// +/// let module = Module(name: "Example") +/// let builder = IRBuilder(module: module) +/// let fun = builder.addFunction("example", +/// type: FunctionType([], VoidType())) +/// // Create and append the entry block +/// let entryBB = fun.appendBasicBlock(named: "entry") +/// // Create and append a standalone basic block +/// let freestanding = BasicBlock(name: "freestanding") +/// fun.append(freestanding) +/// +/// An LLVM function always has the type `FunctionType`. This type is used to +/// determine the number and kind of parameters to the function as well as its +/// return value, if any. The parameter values, which would normally enter +/// the entry block, are instead attached to the function and are accessible +/// via the `parameters` property. +/// +/// Calling Convention +/// ================== +/// +/// By default, all functions in LLVM are invoked with the C calling convention +/// but the exact calling convention of both a function declaration and a +/// `call` instruction are fully configurable. +/// +/// let module = Module(name: "Example") +/// let builder = IRBuilder(module: module) +/// let fun = builder.addFunction("example", +/// type: FunctionType([], VoidType())) +/// // Switch to swiftcc +/// fun.callingConvention = .swift +/// +/// The calling convention of a function and a corresponding call instruction +/// must match or the result is undefined. +/// +/// Sections +/// ======== +/// +/// A function may optionally state the section in the object file it +/// should reside in through the use of a metadata attachment. This can be +/// useful to satisfy target-specific data layout constraints, or to provide +/// some hints to optimizers and linkers. LLVMSwift provides a convenience +/// object called an `MDBuilder` to assist in the creation of this metadata. +/// +/// let mdBuilder = MDBuilder() +/// // __attribute__((hot)) +/// let hotAttr = mdBuilder.buildFunctionSectionPrefix(".hot") +/// +/// let module = Module(name: "Example") +/// let builder = IRBuilder(module: module) +/// let fun = builder.addFunction("example", +/// type: FunctionType([], VoidType())) +/// // Attach the metadata +/// fun.addMetadata(hotAttr, kind: .sectionPrefix) +/// +/// For targets that support it, a function may also specify a COMDAT section. +/// +/// fun.comdat = module.comdat(named: "example") +/// +/// Debug Information +/// ================= +/// +/// A function may also carry debug information through special subprogram +/// nodes. These nodes are intended to capture the structure of the function +/// as it appears in the source so that it is available for inspection by a +/// debugger. See `DIBuilderr.buildFunction` for more information. public class Function: IRGlobal { internal let llvm: LLVMValueRef internal init(llvm: LLVMValueRef) { self.llvm = llvm } + /// Accesses the metadata associated with this function. + /// + /// To build new function metadata, see `DIBuilder.buildFunction`. + public var metadata: FunctionMetadata { + get { return FunctionMetadata(llvm: LLVMGetSubprogram(self.llvm)) } + set { LLVMSetSubprogram(self.llvm, newValue.asMetadata()) } + } + /// Accesses the calling convention for this function. public var callingConvention: CallingConvention { - get { return CallingConvention(rawValue: LLVMGetFunctionCallConv(llvm))! } - set { LLVMSetFunctionCallConv(llvm, newValue.rawValue) } + get { return CallingConvention(llvm: LLVMCallConv(rawValue: LLVMGetFunctionCallConv(llvm))) } + set { LLVMSetFunctionCallConv(llvm, newValue.llvm.rawValue) } } /// Retrieves the entry block of this function. - /// - /// The first basic block in a function is special in two ways: it is - /// immediately executed on entrance to the function, and it is not allowed to - /// have predecessor basic blocks (i.e. there can not be any branches to the - /// entry block of a function). Because the block can have no predecessors, it - /// also cannot have any PHI nodes. public var entryBlock: BasicBlock? { guard let blockRef = LLVMGetEntryBasicBlock(llvm) else { return nil } return BasicBlock(llvm: blockRef) @@ -90,9 +138,14 @@ public class Function: IRGlobal { } } + /// Retrieves the number of basic blocks in this function + public var basicBlockCount: Int { + return Int(LLVMCountBasicBlocks(self.llvm)) + } + /// Computes the address of the specified basic block in this function. /// - /// Taking the address of the entry block is illegal. + /// - WARNING: Taking the address of the entry block is illegal. /// /// This value only has defined behavior when used as an operand to the /// `indirectbr` instruction, or for comparisons against null. Pointer @@ -163,6 +216,11 @@ public class Function: IRGlobal { return params } + /// Retrieves the number of parameter values in this function. + public var parameterCount: Int { + return Int(LLVMCountParams(self.llvm)) + } + /// Appends the named basic block to the body of this function. /// /// - parameter name: The name associated with this basic block. @@ -179,6 +237,13 @@ public class Function: IRGlobal { return BasicBlock(llvm: block) } + /// Appends the named basic block to the body of this function. + /// + /// - parameter basicBlock: The block to append. + public func append(_ basicBlock: BasicBlock) { + LLVMAppendExistingBasicBlock(llvm, basicBlock.asLLVM()) + } + /// Deletes the function from its containing module. /// - note: This does not remove calls to this function from the /// module. Ensure you have removed all instructions that reference diff --git a/Sources/LLVM/FunctionType.swift b/Sources/LLVM/FunctionType.swift index 14d2415a..6524f422 100644 --- a/Sources/LLVM/FunctionType.swift +++ b/Sources/LLVM/FunctionType.swift @@ -8,11 +8,11 @@ import cllvm /// and `MetadataType`. public struct FunctionType: IRType { /// The list of argument types. - public let argTypes: [IRType] + public let parameterTypes: [IRType] /// The return type of this function type. public let returnType: IRType /// Returns whether this function is variadic. - public let isVarArg: Bool + public let isVariadic: Bool /// Creates a function type with the given argument types and return type. /// @@ -21,20 +21,60 @@ public struct FunctionType: IRType { /// - parameter isVarArg: Indicates whether this function type is variadic. /// Defaults to `false`. /// - note: The context of this type is taken from it's `returnType` + @available(*, deprecated, message: "Use the more concise initializer instead", renamed: "FunctionType.init(_:_:variadic:)") public init(argTypes: [IRType], returnType: IRType, isVarArg: Bool = false) { - self.argTypes = argTypes + self.parameterTypes = argTypes self.returnType = returnType - self.isVarArg = isVarArg + self.isVariadic = isVarArg + } + + /// Creates a function type with the given argument types and return type. + /// + /// - parameter parameterTypes: A list of the argument types of the function + /// type. + /// - parameter returnType: The return type of the function type. + /// - parameter variadic: Indicates whether this function type is variadic. + /// Defaults to `false`. + /// - note: The context of this type is taken from it's `returnType` + public init( + _ parameterTypes: [IRType], + _ returnType: IRType, + variadic: Bool = false + ) { + self.parameterTypes = parameterTypes + self.returnType = returnType + self.isVariadic = variadic } /// Retrieves the underlying LLVM type object. public func asLLVM() -> LLVMTypeRef { - var argIRTypes = argTypes.map { $0.asLLVM() as Optional } + var argIRTypes = parameterTypes.map { $0.asLLVM() as Optional } return argIRTypes.withUnsafeMutableBufferPointer { buf in return LLVMFunctionType(returnType.asLLVM(), buf.baseAddress, UInt32(buf.count), - isVarArg.llvm)! + isVariadic.llvm)! } } } + +// MARK: Legacy Accessors + +extension FunctionType { + /// The list of argument types. + @available(*, deprecated, message: "Use FunctionType.parameterTypes instead") + public var argTypes: [IRType] { + return self.parameterTypes + } + /// Returns whether this function is variadic. + @available(*, deprecated, message: "Use FunctionType.isVariadic instead") + public var isVarArg: Bool { + return self.isVariadic + } +} + +extension FunctionType: Equatable { + public static func == (lhs: FunctionType, rhs: FunctionType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() + } +} diff --git a/Sources/LLVM/Global.swift b/Sources/LLVM/Global.swift index aa8b4469..59d79fb0 100644 --- a/Sources/LLVM/Global.swift +++ b/Sources/LLVM/Global.swift @@ -2,86 +2,16 @@ import cllvm #endif -/// Enumerates the supported models of reference of thread-local variables. -/// -/// These models are listed from the most general, but least optimized, to the -/// fastest, but most restrictive. -/// -/// Documentation of these models quotes the [Oracle Linker and Libraries -/// Guide](https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter8-20.html). -public enum ThreadLocalModel { - /// The variable is not thread local and hence has no associated model. - case notThreadLocal - /// Allows reference of all thread-local variables, from either a shared - /// object or a dynamic executable. This model also supports the deferred - /// allocation of a block of thread-local storage when the block is first - /// referenced from a specific thread. - case generalDynamic - /// This model is an optimization of the General Dynamic model. The compiler - /// might determine that a variable is bound locally, or protected, within the - /// object being built. In this case, the compiler instructs the link-editor - /// to statically bind the dynamic `tlsoffset` and use this model. - /// - /// This model provides a performance benefit over the General Dynamic model. - /// Only one call to `tls_get_addr()` is required per function, to determine - /// the address of `dtv0,m`. The dynamic thread-local storage offset, bound at - /// link-edit time, is added to the `dtv0,m` address for each reference. - case localDynamic - /// This model can only reference thread-local variables which are available - /// as part of the initial static thread-local template. This template is - /// composed of all thread-local storage blocks that are available at process - /// startup, plus a small backup reservation. - /// - /// In this model, the thread pointer-relative offset for a given variable `x` - /// is stored in the GOT entry for x. - /// - /// This model can reference a limited number of thread-local variables from - /// shared libraries loaded after initial process startup, such as by means of - /// lazy loading, filters, or `dlopen()`. This access is satisfied from a - /// fixed backup reservation. This reservation can only provide storage for - /// uninitialized thread-local data items. For maximum flexibility, shared - /// objects should reference thread-local variables using a dynamic model of - /// thread-local storage. - case initialExec - /// This model can only reference thread-local variables which are part of the - /// thread-local storage block of the dynamic executable. The link-editor - /// calculates the thread pointer-relative offsets statically, without the - /// need for dynamic relocations, or the extra reference to the GOT. This - /// model can not be used to reference variables outside of the dynamic - /// executable. - case localExec - - internal init(llvm: LLVMThreadLocalMode) { - switch llvm { - case LLVMNotThreadLocal: self = .notThreadLocal - case LLVMGeneralDynamicTLSModel: self = .generalDynamic - case LLVMLocalDynamicTLSModel: self = .localDynamic - case LLVMInitialExecTLSModel: self = .initialExec - case LLVMLocalExecTLSModel: self = .localExec - default: fatalError("unknown thread local mode \(llvm)") - } - } - - static let modeMapping: [ThreadLocalModel: LLVMThreadLocalMode] = [ - .notThreadLocal: LLVMNotThreadLocal, - .generalDynamic: LLVMGeneralDynamicTLSModel, - .localDynamic: LLVMLocalDynamicTLSModel, - .initialExec: LLVMInitialExecTLSModel, - .localExec: LLVMLocalExecTLSModel, - ] - - /// Retrieves the corresponding `LLVMThreadLocalMode`. - public var llvm: LLVMThreadLocalMode { - return ThreadLocalModel.modeMapping[self]! - } -} - /// A `Global` represents a region of memory allocated at compile time instead /// of at runtime. A global variable must either have an initializer, or make /// reference to an external definition that has an initializer. -public struct Global: IRGlobal { +public final class Global: IRGlobal { internal let llvm: LLVMValueRef + internal init(llvm: LLVMValueRef) { + self.llvm = llvm + } + /// Returns whether this global variable has no initializer because it makes /// reference to an initialized value in another translation unit. public var isExternallyInitialized: Bool { @@ -141,3 +71,115 @@ public struct Global: IRGlobal { return llvm } } + +/// Enumerates the supported models of reference of thread-local variables. +/// +/// These models are listed from the most general, but least optimized, to the +/// fastest, but most restrictive in general, as architectural differences +/// play a role in determining the access patterns for thread-local storage. +/// +/// In general, support for thread-local storage in statically-linked +/// applications is limited: some platforms may not even define the behavior of +/// TLS in such cases. This is usually not an issue as statically-linked code +/// only ever has one TLS block, the offset of the variables within that block +/// is known, and support for additional dynamic loading of code in +/// statically-linked code is limited. +/// +/// Computing the thread-specific address of a TLS variable is usually a dynamic +/// process that relies on an ABI-defined function call (usually +/// `__tls_get_addr`) to do the heavy lifting. +/// +/// TLS access models fall into two classes: static and dynamic. Regardless of +/// the actual model used, the dynamic linker must process all relocations +/// for thread-local variables whenever the module is loaded. Some models, +/// therefore, provide for a decrease in the overall number of relocations at +/// a cost of restrictions on which modules can access variables. +public enum ThreadLocalModel { + /// The variable is not thread local and hence has no associated model. + case notThreadLocal + /// Allows reference of all thread-local variables, from either a shared + /// object or a dynamic executable. This model also supports the deferred + /// allocation of a block of thread-local storage when the block is first + /// referenced from a specific thread. Note that the linker is free to + /// optimize accesses using this model to one of the more specific models + /// below which may ultimately defeat lazy allocation of the TLS storagee + /// block. + /// + /// The code generated for this model does not assume that any information + /// about the module or variable offsets is known at link-time. Instead, the + /// exact value of these variables is computed by the dynamic linker at + /// runtime and passeed to `__tls_get_addr` in an architecture-specific way. + /// + /// If possible, this model should be avoided if one of the more specific + /// models applies out of concern for code size and application startup + /// performance. + case generalDynamic + /// This model is an optimization of the `generalDynamic` model. The compiler + /// might determine that a variable is bound locally, or protected, within the + /// object being built. In this case, the compiler instructs the linker + /// to statically bind the dynamic offset of the variable and use this model. + /// + /// This model provides a performance benefit over the General Dynamic model. + /// Only one call to `__tls_get_addr` is required per function, to determine + /// the starting address of the variable within the TLS block for its + /// parent module. Additional accesses can add an offset to this address + /// value for repeated accesses. + /// + /// The optimization available over the `generalDynamic` model is defeated if + /// a variable is only ever accessed once, as its access would incur the + /// same `__tls_get_addr` call and the additional overhead of the offset + /// calculation. + /// + /// The linker cannot, in general, optimize from the general dynamic model + /// to the local dynamic model. + case localDynamic + /// This model can only reference thread-local variables which are available + /// as part of the initial static thread-local template. This template is + /// composed of all thread-local storage blocks that are available at process + /// startup, plus a small backup reservation. + /// + /// In this model, the thread pointer-relative offset for a given variable `x` + /// is stored in the GOT entry for x. + /// + /// This model can reference a limited number of thread-local variables from + /// shared libraries loaded after initial process startup, such as by means of + /// lazy loading, filters, or `dlopen()`. This access is satisfied from a + /// fixed backup reservation. This reservation can only provide storage for + /// uninitialized thread-local data items. For maximum flexibility, shared + /// objects should reference thread-local variables using a dynamic model of + /// thread-local storage. + case initialExec + /// This model is an optimization of the `localDynamic` model. + /// + /// This model can only reference thread-local variables which are part of the + /// thread-local storage block of the dynamic executable. The linker + /// calculates the thread pointer-relative offsets statically, without the + /// need for dynamic relocations, or the extra reference to the GOT. This + /// model can not be used to reference variables outside of the dynamic + /// executable. + case localExec + + internal init(llvm: LLVMThreadLocalMode) { + switch llvm { + case LLVMNotThreadLocal: self = .notThreadLocal + case LLVMGeneralDynamicTLSModel: self = .generalDynamic + case LLVMLocalDynamicTLSModel: self = .localDynamic + case LLVMInitialExecTLSModel: self = .initialExec + case LLVMLocalExecTLSModel: self = .localExec + default: fatalError("unknown thread local mode \(llvm)") + } + } + + static let modeMapping: [ThreadLocalModel: LLVMThreadLocalMode] = [ + .notThreadLocal: LLVMNotThreadLocal, + .generalDynamic: LLVMGeneralDynamicTLSModel, + .localDynamic: LLVMLocalDynamicTLSModel, + .initialExec: LLVMInitialExecTLSModel, + .localExec: LLVMLocalExecTLSModel, + ] + + /// Retrieves the corresponding `LLVMThreadLocalMode`. + public var llvm: LLVMThreadLocalMode { + return ThreadLocalModel.modeMapping[self]! + } +} diff --git a/Sources/LLVM/IRBuilder.swift b/Sources/LLVM/IRBuilder.swift index 6afd3884..baaec84f 100644 --- a/Sources/LLVM/IRBuilder.swift +++ b/Sources/LLVM/IRBuilder.swift @@ -1,350 +1,134 @@ #if SWIFT_PACKAGE import cllvm +import llvmshims #endif -/// Species the behavior that should occur on overflow during mathematical -/// operations. -public enum OverflowBehavior { - /// The result value of the operator is the mathematical result modulo `2^n`, - /// where `n` is the bit width of the result. - case `default` - /// The result value of the operator is a poison value if signed overflow - /// occurs. - case noSignedWrap - /// The result value of the operator is a poison value if unsigned overflow - /// occurs. - case noUnsignedWrap -} - -/// The condition codes available for integer comparison instructions. -public enum IntPredicate { - /// Yields `true` if the operands are equal, false otherwise without sign - /// interpretation. - case equal - /// Yields `true` if the operands are unequal, false otherwise without sign - /// interpretation. - case notEqual - - /// Interprets the operands as unsigned values and yields true if the first is - /// greater than the second. - case unsignedGreaterThan - /// Interprets the operands as unsigned values and yields true if the first is - /// greater than or equal to the second. - case unsignedGreaterThanOrEqual - /// Interprets the operands as unsigned values and yields true if the first is - /// less than the second. - case unsignedLessThan - /// Interprets the operands as unsigned values and yields true if the first is - /// less than or equal to the second. - case unsignedLessThanOrEqual - - /// Interprets the operands as signed values and yields true if the first is - /// greater than the second. - case signedGreaterThan - /// Interprets the operands as signed values and yields true if the first is - /// greater than or equal to the second. - case signedGreaterThanOrEqual - /// Interprets the operands as signed values and yields true if the first is - /// less than the second. - case signedLessThan - /// Interprets the operands as signed values and yields true if the first is - /// less than or equal to the second. - case signedLessThanOrEqual - - static let predicateMapping: [IntPredicate: LLVMIntPredicate] = [ - .equal: LLVMIntEQ, .notEqual: LLVMIntNE, .unsignedGreaterThan: LLVMIntUGT, - .unsignedGreaterThanOrEqual: LLVMIntUGE, .unsignedLessThan: LLVMIntULT, - .unsignedLessThanOrEqual: LLVMIntULE, .signedGreaterThan: LLVMIntSGT, - .signedGreaterThanOrEqual: LLVMIntSGE, .signedLessThan: LLVMIntSLT, - .signedLessThanOrEqual: LLVMIntSLE, - ] - - /// Retrieves the corresponding `LLVMIntPredicate`. - public var llvm: LLVMIntPredicate { - return IntPredicate.predicateMapping[self]! - } -} - -/// The condition codes available for floating comparison instructions. -public enum RealPredicate { - /// No comparison, always returns `false`. - case `false` - /// Ordered and equal. - case orderedEqual - /// Ordered greater than. - case orderedGreaterThan - /// Ordered greater than or equal. - case orderedGreaterThanOrEqual - /// Ordered less than. - case orderedLessThan - /// Ordered less than or equal. - case orderedLessThanOrEqual - /// Ordered and not equal. - case orderedNotEqual - /// Ordered (no nans). - case ordered - /// Unordered (either nans). - case unordered - /// Unordered or equal. - case unorderedEqual - /// Unordered or greater than. - case unorderedGreaterThan - /// Unordered or greater than or equal. - case unorderedGreaterThanOrEqual - /// Unordered or less than. - case unorderedLessThan - /// Unordered or less than or equal. - case unorderedLessThanOrEqual - /// Unordered or not equal. - case unorderedNotEqual - /// No comparison, always returns `true`. - case `true` - - static let predicateMapping: [RealPredicate: LLVMRealPredicate] = [ - .false: LLVMRealPredicateFalse, .orderedEqual: LLVMRealOEQ, - .orderedGreaterThan: LLVMRealOGT, .orderedGreaterThanOrEqual: LLVMRealOGE, - .orderedLessThan: LLVMRealOLT, .orderedLessThanOrEqual: LLVMRealOLE, - .orderedNotEqual: LLVMRealONE, .ordered: LLVMRealORD, .unordered: LLVMRealUNO, - .unorderedEqual: LLVMRealUEQ, .unorderedGreaterThan: LLVMRealUGT, - .unorderedGreaterThanOrEqual: LLVMRealUGE, .unorderedLessThan: LLVMRealULT, - .unorderedLessThanOrEqual: LLVMRealULE, .unorderedNotEqual: LLVMRealUNE, - .true: LLVMRealPredicateTrue, - ] - - /// Retrieves the corresponding `LLVMRealPredicate`. - public var llvm: LLVMRealPredicate { - return RealPredicate.predicateMapping[self]! - } -} - -/// `AtomicOrdering` enumerates available memory ordering semantics. +/// An `IRBuilder` is a helper object that generates LLVM instructions. /// -/// Atomic instructions (`cmpxchg`, `atomicrmw`, `fence`, `atomic load`, and -/// `atomic store`) take ordering parameters that determine which other atomic -/// instructions on the same address they synchronize with. These semantics are -/// borrowed from Java and C++0x, but are somewhat more colloquial. If these -/// descriptions aren’t precise enough, check those specs (see spec references -/// in the atomics guide). fence instructions treat these orderings somewhat -/// differently since they don’t take an address. See that instruction’s -/// documentation for details. -public enum AtomicOrdering: Comparable { - /// A load or store which is not atomic - case notAtomic - /// Lowest level of atomicity, guarantees somewhat sane results, lock free. - /// - /// The set of values that can be read is governed by the happens-before - /// partial order. A value cannot be read unless some operation wrote it. This - /// is intended to provide a guarantee strong enough to model Java’s - /// non-volatile shared variables. This ordering cannot be specified for - /// read-modify-write operations; it is not strong enough to make them atomic - /// in any interesting way. - case unordered - /// Guarantees that if you take all the operations affecting a specific - /// address, a consistent ordering exists. - /// - /// In addition to the guarantees of unordered, there is a single total order - /// for modifications by monotonic operations on each address. All - /// modification orders must be compatible with the happens-before order. - /// There is no guarantee that the modification orders can be combined to a - /// global total order for the whole program (and this often will not be - /// possible). The read in an atomic read-modify-write operation (cmpxchg and - /// atomicrmw) reads the value in the modification order immediately before - /// the value it writes. If one atomic read happens before another atomic read - /// of the same address, the later read must see the same value or a later - /// value in the address’s modification order. This disallows reordering of - /// monotonic (or stronger) operations on the same address. If an address is - /// written monotonic-ally by one thread, and other threads monotonic-ally - /// read that address repeatedly, the other threads must eventually see the - /// write. This corresponds to the C++0x/C1x memory_order_relaxed. - case monotonic - /// Acquire provides a barrier of the sort necessary to acquire a lock to - /// access other memory with normal loads and stores. - /// - /// In addition to the guarantees of monotonic, a synchronizes-with edge may - /// be formed with a release operation. This is intended to model C++’s - /// `memory_order_acquire`. - case acquire - /// Release is similar to Acquire, but with a barrier of the sort necessary to - /// release a lock. - /// - /// In addition to the guarantees of monotonic, if this operation writes a - /// value which is subsequently read by an acquire operation, it - /// synchronizes-with that operation. (This isn’t a complete description; see - /// the C++0x definition of a release sequence.) This corresponds to the - /// C++0x/C1x memory_order_release. - case release - /// provides both an Acquire and a Release barrier (for fences and operations - /// which both read and write memory). - /// - /// This corresponds to the C++0x/C1x memory_order_acq_rel. - case acquireRelease - /// Provides Acquire semantics for loads and Release semantics for stores. - /// - /// In addition to the guarantees of acq_rel (acquire for an operation that - /// only reads, release for an operation that only writes), there is a global - /// total order on all sequentially-consistent operations on all addresses, - /// which is consistent with the happens-before partial order and with the - /// modification orders of all the affected addresses. Each - /// sequentially-consistent read sees the last preceding write to the same - /// address in this global order. This corresponds to the C++0x/C1x - /// `memory_order_seq_cst` and Java volatile. - case sequentiallyConsistent - - private static let orderingMapping: [AtomicOrdering: LLVMAtomicOrdering] = [ - .notAtomic: LLVMAtomicOrderingNotAtomic, - .unordered: LLVMAtomicOrderingUnordered, - .monotonic: LLVMAtomicOrderingMonotonic, - .acquire: LLVMAtomicOrderingAcquire, - .release: LLVMAtomicOrderingRelease, - .acquireRelease: LLVMAtomicOrderingAcquireRelease, - .sequentiallyConsistent: LLVMAtomicOrderingSequentiallyConsistent, - ] - - /// Returns whether the left atomic ordering is strictly weaker than the - /// right atomic order. - public static func <(lhs: AtomicOrdering, rhs: AtomicOrdering) -> Bool { - return lhs.llvm.rawValue < rhs.llvm.rawValue - } - - /// Retrieves the corresponding `LLVMAtomicOrdering`. - public var llvm: LLVMAtomicOrdering { - return AtomicOrdering.orderingMapping[self]! - } -} - -/// `AtomicReadModifyWriteOperation` enumerates the kinds of supported atomic -/// read-write-modify operations. -public enum AtomicReadModifyWriteOperation { - /// Set the new value and return the one old - /// - /// ``` - /// *ptr = val - /// ``` - case xchg - /// Add a value and return the old one - /// - /// ``` - /// *ptr = *ptr + val - /// ``` - case add - /// Subtract a value and return the old one - /// - /// ``` - /// *ptr = *ptr - val - /// ``` - case sub - /// And a value and return the old one - /// - /// ``` - /// *ptr = *ptr & val - /// ``` - case and - /// Not-And a value and return the old one - /// - /// ``` - /// *ptr = ~(*ptr & val) - /// ``` - case nand - /// OR a value and return the old one - /// - /// ``` - /// *ptr = *ptr | val - /// ``` - case or - /// Xor a value and return the old one - /// - /// ``` - /// *ptr = *ptr ^ val - /// ``` - case xor - /// Sets the value if it's greater than the original using a signed comparison - /// and return the old one. - /// - /// ``` - /// // Using a signed comparison - /// *ptr = *ptr > val ? *ptr : val - /// ``` - case max - /// Sets the value if it's Smaller than the original using a signed comparison - /// and return the old one. - /// - /// ``` - /// // Using a signed comparison - /// *ptr = *ptr < val ? *ptr : val - /// ``` - case min - /// Sets the value if it's greater than the original using an unsigned - /// comparison and return the old one. - /// - /// ``` - /// // Using an unsigned comparison - /// *ptr = *ptr > val ? *ptr : val - /// ``` - case umax - /// Sets the value if it's greater than the original using an unsigned - /// comparison and return the old one. - /// - /// ``` - /// // Using an unsigned comparison - /// *ptr = *ptr < val ? *ptr : val - /// ``` - case umin - - static let atomicRMWMapping: [AtomicReadModifyWriteOperation: LLVMAtomicRMWBinOp] = [ - .xchg: LLVMAtomicRMWBinOpXchg, .add: LLVMAtomicRMWBinOpAdd, - .sub: LLVMAtomicRMWBinOpSub, .and: LLVMAtomicRMWBinOpAnd, - .nand: LLVMAtomicRMWBinOpNand, .or: LLVMAtomicRMWBinOpOr, - .xor: LLVMAtomicRMWBinOpXor, .max: LLVMAtomicRMWBinOpMax, - .min: LLVMAtomicRMWBinOpMin, .umax: LLVMAtomicRMWBinOpUMax, - .umin: LLVMAtomicRMWBinOpUMin, - ] - - /// Retrieves the corresponding `LLVMAtomicRMWBinOp`. - public var llvm: LLVMAtomicRMWBinOp { - return AtomicReadModifyWriteOperation.atomicRMWMapping[self]! - } -} - -extension Module { - /// Searches for and retrieves a global variable with the given name in this - /// module if that name references an existing global variable. - /// - /// - parameter name: The name of the global to reference. - /// - /// - returns: A value representing the referenced global if it exists. - public func global(named name: String) -> Global? { - guard let ref = LLVMGetNamedGlobal(llvm, name) else { return nil } - return Global(llvm: ref) - } - - /// Searches for and retrieves a type with the given name in this module if - /// that name references an existing type. - /// - /// - parameter name: The name of the type to create. - /// - /// - returns: A representation of the newly created type with the given name - /// or nil if such a representation could not be created. - public func type(named name: String) -> IRType? { - guard let type = LLVMGetTypeByName(llvm, name) else { return nil } - return convertType(type) - } - - /// Searches for and retrieves a function with the given name in this module - /// if that name references an existing function. - /// - /// - parameter name: The name of the function to create. - /// - /// - returns: A representation of the newly created function with the given - /// name or nil if such a representation could not be created. - public func function(named name: String) -> Function? { - guard let fn = LLVMGetNamedFunction(llvm, name) else { return nil } - return Function(llvm: fn) - } -} - -/// An `IRBuilder` is a helper object that generates LLVM instructions. IR -/// Builders keep track of a position within a function or basic block and has -/// methods to insert instructions at that position. +/// IR builders keep track of a position (the "insertion point") within a +/// module, function, or basic block and has methods to insert instructions at +/// that position. Other features include conveniences to insert calls to +/// C standard library functions like `malloc` and `free`, the creation of +/// global entities like (C) strings, and inline assembly. +/// +/// Threading Considerations +/// ======================== +/// +/// An `IRBuilder` object is not thread safe. It is associated with a single +/// module which is, in turn, associated with a single LLVM context object. +/// In concurrent environments, exactly one IRBuilder should be created per +/// thread, and that thread should be the one that ultimately created its parent +/// module and context. Inserting instructions into the same IR builder object +/// in a concurrent manner will result in malformed IR being generated in +/// non-deterministic ways. If concurrent codegen is needed, a separate LLVM +/// context, module, and IRBuilder should be created on each thread. +/// Once each thread has finished generating code, the resulting modules should +/// be merged together. See `Module.link(_:)` for more information. +/// +/// IR Navigation +/// ============= +/// +/// By default, the insertion point of a builder is undefined. To move the +/// IR builder's cursor, a basic block must be created, but not necessarily +/// inserted into a function. +/// +/// let module = Module(name: "Example") +/// let builder = IRBuilder(module: module) +/// // Create a freestanding basic block and insert an `ret` +/// // instruction into it. +/// let freestanding = BasicBlock(name: "freestanding") +/// // Move the IR builder to the end of the block's instruction list. +/// builder.positionAtEnd(of: freestanding) +/// let ret = builder.buildRetVoid() +/// +/// Instructions serve as a way to position the IR builder to a point before +/// their creation. This allows for instructions to be inserted *before* a +/// given instruction rather than at the very end of a basic block. +/// +/// // Move before the `ret` instruction +/// builder.positionBefore(ret) +/// // Insert an `alloca` instruction before the `ret`. +/// let intAlloca = builder.buildAlloca(type: IntType.int8) +/// // Move before the `alloca` +/// builder.positionBefore(intAlloca) +/// // Insert an `malloc` call before the `alloca`. +/// let intMalloc = builder.buildMalloc(IntType.int8) +/// +/// To insert this block into a function, see `Function.append`. +/// +/// Sometimes it is necessary to reset the insertion point. When the insertion +/// point is reset, instructions built with the IR builder are still created, +/// but are not inserted into a basic block. To clear the insertion point, call +/// `IRBuilder.clearInsertionPosition()`. +/// +/// Building LLVM IR +/// ================ +/// +/// All functions that build instructions are prefixed with `build`. Invoking +/// these functions inserts the appropriate LLVM instruction at the insertion +/// point, assuming it points to a valid location. +/// +/// let module = Module(name: "Example") +/// let builder = IRBuilder(module: module) +/// let fun = builder.addFunction("test", +/// type: FunctionType([ +/// IntType.int8, +/// IntType.int8, +/// ], FloatType.float)) +/// let entry = fun.appendBasicBlock(named: "entry") +/// // Set the insertion point to the entry block of this function +/// builder.positionAtEnd(of: entry) +/// // Build an `add` instruction at the insertion point +/// let result = builder.buildAdd(fun.parameters[0], fun.parameters[1]) +/// +/// Customizing LLVM IR +/// =================== +/// +/// To be well-formed, certain instructions may involve more setup than just +/// being built. In such cases, LLVMSwift will yield a specific instance of +/// `IRInstruction` that will allow for this kind of configuration. +/// +/// A prominent example of this is the PHI node. Building a PHI node produces +/// an empty PHI node - this is not a well-formed instruction. A PHI node must +/// have its incoming basic blocks attached. To do so, `PhiNode.addIncoming(_:)` +/// is called with a list of pairs of incoming values and their enclosing +/// basic blocks. +/// +/// // Build a function that selects one of two floating parameters based +/// // on a given boolean value. +/// let module = Module(name: "Example") +/// let builder = IRBuilder(module: module) +/// let select = builder.addFunction("select", +/// type: FunctionType([ +/// IntType.int1, +/// FloatType.float, +/// FloatType.float, +/// ], FloatType.float)) +/// let entry = select.appendBasicBlock(named: "entry") +/// builder.positionAtEnd(of: entry) +/// +/// let thenBlock = select.appendBasicBlock(named: "then") +/// let elseBlock = select.appendBasicBlock(named: "else") +/// let mergeBB = select.appendBasicBlock(named: "merge") +/// let branch = builder.buildCondBr(condition: select.parameters[0], +/// then: thenBlock, +/// else: elseBlock) +/// builder.positionAtEnd(of: thenBlock) +/// let opThen = builder.buildAdd(select.parameters[1], select.parameters[2]) +/// builder.buildBr(mergeBB) +/// builder.positionAtEnd(of: elseBlock) +/// let opElse = builder.buildSub(select.parameters[1], select.parameters[2]) +/// builder.buildBr(mergeBB) +/// builder.positionAtEnd(of: mergeBB) +/// +/// // Build the PHI node +/// let phi = builder.buildPhi(FloatType.float) +/// // Attach the incoming blocks. +/// phi.addIncoming([ +/// (opThen, thenBlock), +/// (opElse, elseBlock), +/// ]) +/// builder.buildRet(phi) public class IRBuilder { internal let llvm: LLVMBuilderRef @@ -359,8 +143,15 @@ public class IRBuilder { self.llvm = LLVMCreateBuilderInContext(module.context.llvm) } - // MARK: IR Navigation + /// Deinitialize this value and dispose of its resources. + deinit { + LLVMDisposeBuilder(llvm) + } +} + +// MARK: IR Navigation +extension IRBuilder { /// Repositions the IR Builder at the end of the given basic block. /// /// - parameter block: The basic block to reposition the IR Builder after. @@ -371,7 +162,7 @@ public class IRBuilder { /// Repositions the IR Builder before the start of the given instruction. /// /// - parameter inst: The instruction to reposition the IR Builder before. - public func positionBefore(_ inst: IRValue) { + public func positionBefore(_ inst: IRInstruction) { LLVMPositionBuilderBefore(llvm, inst.asLLVM()) } @@ -383,7 +174,7 @@ public class IRBuilder { /// /// - parameter inst: The instruction to reposition the IR Builder before. /// - parameter block: The basic block to reposition the IR builder in. - public func position(_ inst: IRValue, block: BasicBlock) { + public func position(_ inst: IRInstruction, block: BasicBlock) { LLVMPositionBuilder(llvm, block.llvm, inst.asLLVM()) } @@ -394,8 +185,6 @@ public class IRBuilder { LLVMClearInsertionPosition(llvm) } - // MARK: Instruction Insertion - /// Gets the basic block built instructions will be inserted into. public var insertBlock: BasicBlock? { guard let blockRef = LLVMGetInsertBlock(llvm) else { return nil } @@ -411,16 +200,35 @@ public class IRBuilder { /// /// - parameter inst: The instruction to insert. /// - parameter name: The name for the newly inserted instruction. - public func insert(_ inst: IRValue, name: String? = nil) { + public func insert(_ inst: IRInstruction, name: String? = nil) { if let name = name { LLVMInsertIntoBuilderWithName(llvm, inst.asLLVM(), name) } else { LLVMInsertIntoBuilder(llvm, inst.asLLVM()) } } +} + +// MARK: Debug Information + +extension IRBuilder { + /// Access location information used by debugging information. + public var currentDebugLocation: DebugLocation? { + get { return LLVMGetCurrentDebugLocation2(self.llvm).map(DebugLocation.init(llvm:)) } + set { LLVMSetCurrentDebugLocation2(self.llvm, newValue?.asMetadata()) } + } - // MARK: Convenience Instructions + /// Set the floating point math metadata to be used for floating-point + /// operations. + public var defaultFloatingPointMathTag: MDNode? { + get { return LLVMBuilderGetDefaultFPMathTag(self.llvm).map(MDNode.init(llvm:)) } + set { LLVMBuilderSetDefaultFPMathTag(self.llvm, newValue?.asMetadata()) } + } +} +// MARK: Convenience Instructions + +extension IRBuilder { /// Builds the specified binary operation instruction with the given arguments. /// /// - parameter op: The operation to build. @@ -448,9 +256,61 @@ public class IRBuilder { return LLVMBuildCast(llvm, op.llvm, value.asLLVM(), type.asLLVM(), name) } - // MARK: Arithmetic Instructions + /// Builds a cast operation from a value of pointer type to any other + /// integral, pointer, or vector of integral/pointer type. + /// + /// There are a number of restrictions on the form of the input value and + /// destination type. The source value of a pointer cast must be either a + /// pointer or a vector of pointers. The destination type must either be + /// an integer type, a pointer type, or a vector type with integral or pointer + /// element type. + /// + /// If the destination type is an integral type or a vector of integral + /// elements, this builds a `ptrtoint` instruction. Else, if the destination + /// is a pointer type or vector of pointer type, and it has an address space + /// that differs from the address space of the source value, an + /// `addrspacecast` instruction is built. If none of these are true, a + /// `bitcast` instruction is built. + /// + /// - Parameters: + /// - value: The value to cast. The value must have pointer type. + /// - type: The destination type to cast to. This must be a pointer type, + /// integer type, or vector of the same. + /// - name: The name for the newly inserted instruction. + /// - Returns: A value representing the result of casting the given value to + /// the given destination type using the appropriate pointer cast operation. + public func buildPointerCast(of value: IRValue, to type: IRType, name: String = "") -> IRValue { + precondition(value.type is PointerType || value.type.scalarType is PointerType, + "cast value must be a pointer or vector of pointers") + precondition(type.scalarType is IntType || type.scalarType is PointerType, + "destination type must be int, pointer, or vector of int/pointer") + + return LLVMBuildPointerCast(llvm, value.asLLVM(), type.asLLVM(), name) + } + + /// Builds a cast operation from a value of integral type to given integral + /// type by zero-extension, sign-extension, bitcast, or truncation + /// as necessary. + /// + /// - Parameters: + /// - value: The value to cast. + /// - type: The destination integer type to cast to. + /// - signed: If true, if an extension is required it will be a + /// sign-extension. Else, all required extensions will be + /// zero-extensions. + /// - name: The name for the newly inserted instruction. + /// - Returns: A value reprresenting the result of casting the given value to + /// the given destination integer type using the appropriate + /// integral cast operation. + public func buildIntCast(of value: IRValue, to type: IntType, signed: Bool = true, name: String = "") -> IRValue { + return LLVMBuildIntCast2(llvm, value.asLLVM(), type.asLLVM(), signed.llvm, name) + } +} + +// MARK: Arithmetic Instructions - /// Builds a negation instruction with the given value as an operand. +extension IRBuilder { + /// Build a negation instruction with the given value as an operand. /// /// Whether an integer or floating point negate instruction is built is /// determined by the type of the given value. Providing an operand that is @@ -481,7 +341,7 @@ public class IRBuilder { fatalError("Can only negate value of int or float types") } - /// Builds an add instruction with the given values as operands. + /// Build an add instruction with the given values as operands. /// /// Whether an integer or floating point add instruction is built is /// determined by the type of the first given value. Providing operands that @@ -516,7 +376,7 @@ public class IRBuilder { fatalError("Can only add value of int, float, or vector types") } - /// Builds a subtract instruction with the given values as operands. + /// Build a subtract instruction with the given values as operands. /// /// Whether an integer or floating point subtract instruction is built is /// determined by the type of the first given value. Providing operands that @@ -551,7 +411,7 @@ public class IRBuilder { fatalError("Can only subtract value of int or float types") } - /// Builds a multiply instruction with the given values as operands. + /// Build a multiply instruction with the given values as operands. /// /// Whether an integer or floating point multiply instruction is built is /// determined by the type of the first given value. Providing operands that @@ -713,10 +573,12 @@ public class IRBuilder { } return LLVMBuildFCmp(llvm, predicate.llvm, lhsVal, rhsVal, name) } +} - // MARK: Logical Instructions +// MARK: Logical Instructions - /// Builds a bitwise logical not with the given value as an operand. +extension IRBuilder { + /// Build a bitwise logical not with the given value as an operand. /// /// - parameter val: The value to negate. /// - parameter name: The name for the newly inserted instruction. @@ -726,7 +588,7 @@ public class IRBuilder { return LLVMBuildNot(llvm, val.asLLVM(), name) } - /// Builds a bitwise logical exclusive OR with the given values as operands. + /// Build a bitwise logical exclusive OR with the given values as operands. /// /// - parameter lhs: The first operand. /// - parameter rhs: The second operand. @@ -738,7 +600,7 @@ public class IRBuilder { return LLVMBuildXor(llvm, lhs.asLLVM(), rhs.asLLVM(), name) } - /// Builds a bitwise logical OR with the given values as operands. + /// Build a bitwise logical OR with the given values as operands. /// /// - parameter lhs: The first operand. /// - parameter rhs: The second operand. @@ -750,7 +612,7 @@ public class IRBuilder { return LLVMBuildOr(llvm, lhs.asLLVM(), rhs.asLLVM(), name) } - /// Builds a bitwise logical AND with the given values as operands. + /// Build a bitwise logical AND with the given values as operands. /// /// - parameter lhs: The first operand. /// - parameter rhs: The second operand. @@ -762,7 +624,7 @@ public class IRBuilder { return LLVMBuildAnd(llvm, lhs.asLLVM(), rhs.asLLVM(), name) } - /// Builds a left-shift instruction of the first value by an amount in the + /// Build a left-shift instruction of the first value by an amount in the /// second value. /// /// - parameter lhs: The first operand. @@ -776,7 +638,7 @@ public class IRBuilder { return LLVMBuildShl(llvm, lhs.asLLVM(), rhs.asLLVM(), name) } - /// Builds a right-shift instruction of the first value by an amount in the + /// Build a right-shift instruction of the first value by an amount in the /// second value. If `isArithmetic` is true the value of the first operand is /// bitshifted with sign extension. Else the value is bitshifted with /// zero-fill. @@ -798,9 +660,11 @@ public class IRBuilder { return LLVMBuildLShr(llvm, lhs.asLLVM(), rhs.asLLVM(), name) } } +} - // MARK: Conditional Instructions +// MARK: Conditional Instructions +extension IRBuilder { /// Build a phi node with the given type acting as the result of any incoming /// basic blocks. /// @@ -823,7 +687,7 @@ public class IRBuilder { /// - parameter name: The name for the newly inserted instruction. /// /// - returns: A value representing the value selected for by the condition. - public func buildSelect(_ cond: IRValue, then: IRValue, else: IRValue, name: String = "") -> IRValue { + public func buildSelect(_ cond: IRValue, then: IRValue, else: IRValue, name: String = "") -> IRInstruction { if let ty = cond.type as? IntType { precondition(ty.width == 1, "Switch statement condition must have bitwidth of 1, instead has bitwidth of \(ty.width)") return LLVMBuildSelect(llvm, cond.asLLVM(), then.asLLVM(), `else`.asLLVM(), name) @@ -838,10 +702,19 @@ public class IRBuilder { /// Build a branch table that branches on the given value with the given /// default basic block. /// - /// The ‘switch‘ instruction is used to transfer control flow to one of - /// several different places. It is a generalization of the ‘br‘ instruction, + /// The `switch` instruction is used to transfer control flow to one of + /// several different places. It is a generalization of the `br` instruction, /// allowing a branch to occur to one of many possible destinations. /// + /// This function returns a value that acts as a representation of the branch + /// table for the `switch` instruction. When the `switch` instruction is + /// executed, this table is searched for the given value. If the value is + /// found, control flow is transferred to the corresponding destination; + /// otherwise, control flow is transferred to the default destination + /// specified by the `else` block. + /// + /// To add branches to the `switch` table, see `Switch.addCase(_:_:)`. + /// /// - parameter value: The value to compare. /// - parameter else: The default destination for control flow should the /// value not match a case in the branch table. @@ -854,9 +727,11 @@ public class IRBuilder { `else`.asLLVM(), UInt32(caseCount))!) } +} - // MARK: Declaration Instructions +// MARK: Declaration Instructions +extension IRBuilder { /// Build a named function body with the given type. /// /// - parameter name: The name of the newly defined function. @@ -883,22 +758,35 @@ public class IRBuilder { } return type } +} - // MARK: Terminator Instructions +// MARK: Terminator Instructions +extension IRBuilder { /// Build an unconditional branch to the given basic block. /// + /// The `br` instruction is used to cause control flow to transfer to a + /// different basic block in the current function. There are two forms of this + /// instruction, corresponding to a conditional branch and an unconditional + /// branch. To build a conditional branch, see + /// `buildCondBr(condition:then:`else`:)`. + /// /// - parameter block: The target block to transfer control flow to. /// /// - returns: A value representing `void`. @discardableResult - public func buildBr(_ block: BasicBlock) -> IRValue { + public func buildBr(_ block: BasicBlock) -> IRInstruction { return LLVMBuildBr(llvm, block.llvm) } /// Build a condition branch that branches to the first basic block if the /// provided condition is `true`, otherwise to the second basic block. /// + /// The `br` instruction is used to cause control flow to transfer to a + /// different basic block in the current function. There are two forms of this + /// instruction, corresponding to a conditional branch and an unconditional + /// branch. To build an unconditional branch, see `buildBr(_:)`. + /// /// - parameter condition: A value of type `i1` that determines which basic /// block to transfer control flow to. /// - parameter then: The basic block to transfer control flow to if the @@ -908,12 +796,24 @@ public class IRBuilder { /// /// - returns: A value representing `void`. @discardableResult - public func buildCondBr(condition: IRValue, then: BasicBlock, `else`: BasicBlock) -> IRValue { - return LLVMBuildCondBr(llvm, condition.asLLVM(), then.asLLVM(), `else`.asLLVM()) + public func buildCondBr( + condition: IRValue, then: BasicBlock, `else`: BasicBlock) -> IRInstruction { + guard let instr: IRInstruction = LLVMBuildCondBr(llvm, condition.asLLVM(), then.asLLVM(), `else`.asLLVM()) else { + fatalError("Unable to build conditional branch") + } + return instr } /// Build an indirect branch to a label within the current function. /// + /// The `indirectbr` instruction implements an indirect branch to a label + /// within the current function, whose address is specified by the `address` + /// parameter. + /// + /// All possible destination blocks must be listed in the `destinations` list, + /// otherwise this instruction has undefined behavior. This implies that jumps + /// to labels defined in other functions have undefined behavior as well. + /// /// - parameter address: The address of the label to branch to. /// - parameter destinations: The set of possible destinations the address may /// point to. The same block may appear multiple times in this list, though @@ -921,7 +821,7 @@ public class IRBuilder { /// /// - returns: An IRValue representing `void`. @discardableResult - public func buildIndirectBr(address: BasicBlock.Address, destinations: [BasicBlock]) -> IRValue { + public func buildIndirectBr(address: BasicBlock.Address, destinations: [BasicBlock]) -> IRInstruction { guard let ret = LLVMBuildIndirectBr(llvm, address.asLLVM(), UInt32(destinations.count)) else { fatalError("Unable to build indirect branch to address \(address)") } @@ -931,41 +831,61 @@ public class IRBuilder { return ret } - /// Builds a return from the current function back to the calling function + /// Build a return from the current function back to the calling function /// with the given value. /// + /// Returning a value with a type that does not correspond to the return + /// type of the current function is a fatal condition. + /// + /// There are two forms of the `ret` instruction: one that returns a value and + /// then causes control flow, and one that just causes control flow to occur. + /// To build the `ret` that does not return a value use `buildRetVoid()`. + /// /// - parameter val: The value to return from the current function. /// /// - returns: A value representing `void`. @discardableResult - public func buildRet(_ val: IRValue) -> IRValue { + public func buildRet(_ val: IRValue) -> IRInstruction { return LLVMBuildRet(llvm, val.asLLVM()) } - /// Builds a void return from the current function. + /// Build a void return from the current function. + /// + /// If the current function does not have a `Void` return value, failure to + /// return a falue is a fatal condition. + /// + /// There are two forms of the `ret` instruction: one that returns a value and + /// then causes control flow, and one that just causes control flow to occur. + /// To build the `ret` that returns a value use `buildRet(_:)`. /// /// - returns: A value representing `void`. @discardableResult - public func buildRetVoid() -> IRValue { + public func buildRetVoid() -> IRInstruction { return LLVMBuildRetVoid(llvm) } - /// Builds an unreachable instruction in the current function. + /// Build an unreachable instruction in the current function. + /// + /// The `unreachable` instruction has no defined semantics. This instruction + /// is used to inform the optimizer that a particular portion of the code is + /// not reachable. This can be used to indicate that the code after a + /// no-return function cannot be reached, and other facts. /// /// - returns: A value representing `void`. @discardableResult - public func buildUnreachable() -> IRValue { + public func buildUnreachable() -> IRInstruction { return LLVMBuildUnreachable(llvm) } /// Build a return from the current function back to the calling function with /// the given array of values as members of an aggregate. /// - /// - parameter values: The values to insert as members of the returned aggregate. + /// - parameter values: The values to insert as members of the returned + /// aggregate. /// /// - returns: A value representing `void`. @discardableResult - public func buildRetAggregate(of values: [IRValue]) -> IRValue { + public func buildRetAggregate(of values: [IRValue]) -> IRInstruction { var values = values.map { $0.asLLVM() as Optional } return values.withUnsafeMutableBufferPointer { buf in return LLVMBuildAggregateRet(llvm, buf.baseAddress!, UInt32(buf.count)) @@ -986,9 +906,11 @@ public class IRBuilder { return Call(llvm: LLVMBuildCall(llvm, fn.asLLVM(), buf.baseAddress!, UInt32(buf.count), name)) } } +} - // MARK: Exception Handling Instructions +// MARK: Exception Handling Instructions +extension IRBuilder { /// Build a call to the given function with the given arguments with the /// possibility of control transfering to either the `next` basic block or /// the `catch` basic block if an exception occurs. @@ -999,6 +921,10 @@ public class IRBuilder { /// mechanism, control is interrupted and continued at the dynamically nearest /// `exception` label. /// + /// The `catch` block is a landing pad for the exception. As such, the first + /// instruction of that block is required to be the `landingpad` instruction, + /// which contains the information about the behavior of the program after + /// unwinding happens. /// /// - parameter fn: The function to invoke. /// - parameter args: A list of arguments. @@ -1052,10 +978,10 @@ public class IRBuilder { /// /// - returns: A value of the given type representing the result of matching /// a clause during unwinding. - public func buildLandingPad(returning type: IRType, personalityFn: Function? = nil, clauses: [LandingPadClause], cleanup: Bool = false, name: String = "") -> IRValue { + public func buildLandingPad(returning type: IRType, personalityFn: Function? = nil, clauses: [LandingPadClause], cleanup: Bool = false, name: String = "") -> IRInstruction { precondition(cleanup || !clauses.isEmpty, "Landing pad must be created with clauses or as cleanup") - let lp : IRValue = LLVMBuildLandingPad(llvm, type.asLLVM(), personalityFn?.asLLVM(), UInt32(clauses.count), name) + let lp: IRInstruction = LLVMBuildLandingPad(llvm, type.asLLVM(), personalityFn?.asLLVM(), UInt32(clauses.count), name) for clause in clauses { LLVMAddClause(lp.asLLVM(), clause.asLLVM()) } @@ -1069,7 +995,7 @@ public class IRBuilder { /// /// When all cleanups are finished, if an exception is not handled by the /// current function, unwinding resumes by calling the resume instruction, - /// passing in the result of the `landingpad` instruction for the original + /// passing in the result of the `landingpad` instruction for the original /// landing pad. /// /// - parameter: A value representing the result of the original landing pad. @@ -1094,27 +1020,54 @@ public class IRBuilder { public func buildVAArg(_ list: IRValue, type: IRType, name: String = "") -> IRValue { return LLVMBuildVAArg(llvm, list.asLLVM(), type.asLLVM(), name) } +} - // MARK: Memory Access Instructions +// MARK: Memory Access Instructions +extension IRBuilder { /// Build an `alloca` to allocate stack memory to hold a value of the given /// type. /// + /// The `alloca` instruction allocates `sizeof()*count` bytes of + /// memory on the runtime stack, returning a pointer of the appropriate type + /// to the program. If `count` is specified, it is the number of elements + /// allocated, otherwise `count` is defaulted to be one. If a constant + /// alignment is specified, the value result of the allocation is guaranteed + /// to be aligned to at least that boundary. The alignment may not be + /// greater than `1 << 29`. If not specified, or if zero, the target will + /// choose a default value that is convenient and compatible with the type. + /// + /// The returned value is allocated in the address space specified in the data layout string for the target. If + /// no such value is specified, the value is allocated in the default address space. + /// /// - parameter type: The sized type used to determine the amount of stack /// memory to allocate. + /// - parameter count: An optional number of slots to allocate, to simulate a + /// C array. /// - parameter alignment: The alignment of the access. /// - parameter name: The name for the newly inserted instruction. /// /// - returns: A value representing `void`. - public func buildAlloca(type: IRType, alignment: Int = 0, name: String = "") -> IRValue { - let allocaInst = LLVMBuildAlloca(llvm, type.asLLVM(), name)! - LLVMSetAlignment(allocaInst, UInt32(alignment)) + public func buildAlloca(type: IRType, count: IRValue? = nil, + alignment: Alignment = .zero, name: String = "") -> IRInstruction { + let allocaInst: LLVMValueRef + if let count = count { + allocaInst = LLVMBuildArrayAlloca(llvm, type.asLLVM(), count.asLLVM(), name) + } else { + allocaInst = LLVMBuildAlloca(llvm, type.asLLVM(), name)! + } + if !alignment.isZero { + LLVMSetAlignment(allocaInst, alignment.rawValue) + } return allocaInst } - /// Builds a store instruction that stores the first value into the location + /// Build a store instruction that stores the first value into the location /// given in the second value. /// + /// If alignment is not specified, or if zero, the target will choose a default + /// value that is convenient and compatible with the type. + /// /// - parameter val: The source value. /// - parameter ptr: The destination pointer to store into. /// - parameter ordering: The ordering effect of the fence for this store, @@ -1124,18 +1077,24 @@ public class IRBuilder { /// /// - returns: A value representing `void`. @discardableResult - public func buildStore(_ val: IRValue, to ptr: IRValue, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false, alignment: Int = 0) -> IRValue { + public func buildStore(_ val: IRValue, to ptr: IRValue, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false, alignment: Alignment = .zero) -> IRInstruction { let storeInst = LLVMBuildStore(llvm, val.asLLVM(), ptr.asLLVM())! LLVMSetOrdering(storeInst, ordering.llvm) LLVMSetVolatile(storeInst, volatile.llvm) - LLVMSetAlignment(storeInst, UInt32(alignment)) + if !alignment.isZero { + LLVMSetAlignment(storeInst, alignment.rawValue) + } return storeInst } - /// Builds a load instruction that loads a value from the location in the + /// Build a load instruction that loads a value from the location in the /// given value. /// + /// If alignment is not specified, or if zero, the target will choose a default + /// value that is convenient and compatible with the type. + /// /// - parameter ptr: The pointer value to load from. + /// - parameter type: The type of value loaded from the given pointer. /// - parameter ordering: The ordering effect of the fence for this load, /// if any. Defaults to a nonatomic load. /// - parameter volatile: Whether this is a load from a volatile memory location. @@ -1144,15 +1103,18 @@ public class IRBuilder { /// /// - returns: A value representing the result of a load from the given /// pointer value. - public func buildLoad(_ ptr: IRValue, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false, alignment: Int = 0, name: String = "") -> IRValue { - let loadInst = LLVMBuildLoad(llvm, ptr.asLLVM(), name)! + public func buildLoad(_ ptr: IRValue, type: IRType, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false, alignment: Alignment = .zero, name: String = "") -> IRInstruction { + let loadInst = LLVMBuildLoad2(llvm, type.asLLVM(), ptr.asLLVM(), name)! LLVMSetOrdering(loadInst, ordering.llvm) LLVMSetVolatile(loadInst, volatile.llvm) - LLVMSetAlignment(loadInst, UInt32(alignment)) + if !alignment.isZero { + LLVMSetAlignment(loadInst, alignment.rawValue) + } return loadInst } - /// Builds a `GEP` (Get Element Pointer) instruction with a resultant value + + /// Build a `GEP` (Get Element Pointer) instruction with a resultant value /// that is undefined if the address is outside the actual underlying /// allocated object and not the address one-past-the-end. /// @@ -1161,67 +1123,78 @@ public class IRBuilder { /// around its semantics and correct usage. /// /// - parameter ptr: The base address for the index calculation. + /// - parameter type: The type used to calculate pointer offsets. /// - parameter indices: A list of indices that indicate which of the elements /// of the aggregate object are indexed. /// - parameter name: The name for the newly inserted instruction. /// /// - returns: A value representing the address of a subelement of the given /// aggregate data structure value. - public func buildInBoundsGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue { + public func buildInBoundsGEP(_ ptr: IRValue, type: IRType, indices: [IRValue], name: String = "") -> IRValue { var vals = indices.map { $0.asLLVM() as Optional } return vals.withUnsafeMutableBufferPointer { buf in - return LLVMBuildInBoundsGEP(llvm, ptr.asLLVM(), buf.baseAddress, UInt32(buf.count), name) + return LLVMBuildInBoundsGEP2(llvm, type.asLLVM(), ptr.asLLVM(), buf.baseAddress, UInt32(buf.count), name) } } - /// Builds a GEP (Get Element Pointer) instruction. + /// Build a GEP (Get Element Pointer) instruction. /// /// The `GEP` instruction is often the source of confusion. LLVM [provides a /// document](http://llvm.org/docs/GetElementPtr.html) to answer questions /// around its semantics and correct usage. /// /// - parameter ptr: The base address for the index calculation. + /// - parameter type: The type used to calculate pointer offsets. /// - parameter indices: A list of indices that indicate which of the elements /// of the aggregate object are indexed. /// - parameter name: The name for the newly inserted instruction. /// /// - returns: A value representing the address of a subelement of the given /// aggregate data structure value. - public func buildGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue { + public func buildGEP(_ ptr: IRValue, type: IRType, indices: [IRValue], name: String = "") -> IRValue { var vals = indices.map { $0.asLLVM() as Optional } return vals.withUnsafeMutableBufferPointer { buf in - return LLVMBuildGEP(llvm, ptr.asLLVM(), buf.baseAddress, UInt32(buf.count), name) + return LLVMBuildGEP2(llvm, type.asLLVM(), ptr.asLLVM(), buf.baseAddress, UInt32(buf.count), name) } } - /// Builds a GEP (Get Element Pointer) instruction suitable for indexing into - /// a struct. + /// Build a GEP (Get Element Pointer) instruction suitable for indexing into + /// a struct of a given type. /// /// - parameter ptr: The base address for the index calculation. + /// - parameter type: The type of the struct to index into. /// - parameter index: The offset from the base for the index calculation. /// - parameter name: The name for the newly inserted instruction. /// /// - returns: A value representing the address of a subelement of the given /// struct value. - public func buildStructGEP(_ ptr: IRValue, index: Int, name: String = "") -> IRValue { - return LLVMBuildStructGEP(llvm, ptr.asLLVM(), UInt32(index), name) + public func buildStructGEP(_ ptr: IRValue, type: IRType, index: Int, name: String = "") -> IRValue { + return LLVMBuildStructGEP2(llvm, type.asLLVM(), ptr.asLLVM(), UInt32(index), name) } - - /// Builds an ExtractValue instruction to retrieve an indexed value from a + + /// Build an ExtractValue instruction to retrieve an indexed value from a /// struct or array value. /// + /// `extractvalue` function like a GEP, but has different indexing semantics: + /// + /// - Since the value being indexed is not a pointer, the first index is + /// omitted and assumed to be zero. + /// - Not only struct indices but also array indices must be in bounds. + /// /// - parameter value: The struct or array you're indexing into. /// - parameter index: The index at which to extract. /// /// - returns: The value in the struct at the provided index. public func buildExtractValue(_ value: IRValue, index: Int, - name: String = "") -> IRValue { + name: String = "") -> IRValue { return LLVMBuildExtractValue(llvm, value.asLLVM(), UInt32(index), name) } +} - // MARK: Null Test Instructions +// MARK: Null Test Instructions - /// Builds a comparision instruction that returns whether the given operand is +extension IRBuilder { + /// Build a comparision instruction that returns whether the given operand is /// `null`. /// /// - parameter val: The value to test. @@ -1233,7 +1206,7 @@ public class IRBuilder { return LLVMBuildIsNull(llvm, val.asLLVM(), name) } - /// Builds a comparision instruction that returns whether the given operand is + /// Build a comparision instruction that returns whether the given operand is /// not `null`. /// /// - parameter val: The value to test. @@ -1244,10 +1217,12 @@ public class IRBuilder { public func buildIsNotNull(_ val: IRValue, name: String = "") -> IRValue { return LLVMBuildIsNotNull(llvm, val.asLLVM(), name) } +} - // MARK: Conversion Instructions +// MARK: Conversion Instructions - /// Builds an instruction that either performs a truncation or a bitcast of +extension IRBuilder { + /// Build an instruction that either performs a truncation or a bitcast of /// the given value to a value of the given type. /// /// - parameter val: The value to cast or truncate. @@ -1260,7 +1235,7 @@ public class IRBuilder { return LLVMBuildTruncOrBitCast(llvm, val.asLLVM(), type.asLLVM(), name) } - /// Builds an instruction that either performs a zero extension or a bitcast of + /// Build an instruction that either performs a zero extension or a bitcast of /// the given value to a value of the given type with a wider width. /// /// - parameter val: The value to zero extend. @@ -1273,9 +1248,17 @@ public class IRBuilder { return LLVMBuildZExtOrBitCast(llvm, val.asLLVM(), type.asLLVM(), name) } - /// Builds a bitcast instruction to convert the given value to a value of the + /// Build a bitcast instruction to convert the given value to a value of the /// given type by just copying the bit pattern. /// + /// The `bitcast` instruction is always a no-op cast because no bits change + /// with this conversion. The conversion is done as if the value had been + /// stored to memory and read back as the given type. Pointer (or vector of + /// pointer) types may only be converted to other pointer (or vector of + /// pointer) types with the same address space through this instruction. To + /// convert pointers to other types, see `buildIntToPtr(_:type:name:)` or + /// `buildPtrToInt(_:type:name:)`. + /// /// - parameter val: The value to bitcast. /// - parameter type: The destination type. /// - parameter name: The name for the newly inserted instruction. @@ -1286,7 +1269,7 @@ public class IRBuilder { return LLVMBuildBitCast(llvm, val.asLLVM(), type.asLLVM(), name) } - /// Builds a cast instruction to convert the given floating-point value to a + /// Build a cast instruction to convert the given floating-point value to a /// value of the given type. /// /// - parameter val: The value to cast. @@ -1299,16 +1282,25 @@ public class IRBuilder { return LLVMBuildFPCast(llvm, val.asLLVM(), type.asLLVM(), name) } - /// Builds an address space cast instruction that converts a pointer value + /// Build an address space cast instruction that converts a pointer value /// to a given type in a different address space. /// + /// The `addrspacecast` instruction can be a no-op cast or a complex value + /// modification, depending on the target and the address space pair. Pointer + /// conversions within the same address space must be performed with the + /// `bitcast` instruction. Note that if the address space conversion is legal + /// then both result and operand refer to the same memory location. + /// + /// This instruction must be used in lieu of a `bitcast` even if the cast is between + /// types of the same size. + /// /// The address spaces of the value and the destination pointer types must /// be distinct. public func buildAddrSpaceCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue { return LLVMBuildAddrSpaceCast(llvm, val.asLLVM(), type.asLLVM(), name) } - /// Builds a truncate instruction to truncate the given value to the given + /// Build a truncate instruction to truncate the given value to the given /// type with a shorter width. /// /// - parameter val: The value to truncate. @@ -1321,7 +1313,7 @@ public class IRBuilder { return LLVMBuildTrunc(llvm, val.asLLVM(), type.asLLVM(), name) } - /// Builds a sign extension instruction to sign extend the given value to + /// Build a sign extension instruction to sign extend the given value to /// the given type with a wider width. /// /// - parameter val: The value to sign extend. @@ -1334,7 +1326,7 @@ public class IRBuilder { return LLVMBuildSExt(llvm, val.asLLVM(), type.asLLVM(), name) } - /// Builds a zero extension instruction to zero extend the given value to the + /// Build a zero extension instruction to zero extend the given value to the /// given type with a wider width. /// /// - parameter val: The value to zero extend. @@ -1347,9 +1339,16 @@ public class IRBuilder { return LLVMBuildZExt(llvm, val.asLLVM(), type.asLLVM(), name) } - /// Builds an integer-to-pointer instruction to convert the given value to the + /// Build an integer-to-pointer instruction to convert the given value to the /// given pointer type. /// + /// The `inttoptr` instruction converts the given value to the given pointer + /// type by applying either a zero extension or a truncation depending on the + /// size of the integer value. If value is larger than the size of a pointer + /// then a truncation is done. If value is smaller than the size of a pointer + /// then a zero extension is done. If they are the same size, nothing is done + /// (no-op cast). + /// /// - parameter val: The integer value. /// - parameter type: The destination pointer type. /// - parameter name: The name for the newly inserted instruction. @@ -1360,9 +1359,17 @@ public class IRBuilder { return LLVMBuildIntToPtr(llvm, val.asLLVM(), type.asLLVM(), name) } - /// Builds a pointer-to-integer instruction to convert the given pointer value + /// Build a pointer-to-integer instruction to convert the given pointer value /// to the given integer type. /// + /// The `ptrtoint` instruction converts the given pointer value to the given + /// integer type by interpreting the pointer value as an integer and either + /// truncating or zero extending that value to the size of the integer type. + /// If the pointer value is smaller than the integer type then a zero + /// extension is done. If the pointer value is larger than the integer type + /// then a truncation is done. If they are the same size, then nothing is done + /// (no-op cast) other than a type change. + /// /// - parameter val: The pointer value. /// - parameter type: The destination integer type. /// - parameter name: The name for the newly inserted instruction. @@ -1373,7 +1380,7 @@ public class IRBuilder { return LLVMBuildPtrToInt(llvm, val.asLLVM(), type.asLLVM(), name) } - /// Builds an integer-to-floating instruction to convert the given integer + /// Build an integer-to-floating instruction to convert the given integer /// value to the given floating type. /// /// - parameter val: The integer value. @@ -1391,7 +1398,7 @@ public class IRBuilder { } } - /// Builds a floating-to-integer instruction to convert the given floating + /// Build a floating-to-integer instruction to convert the given floating /// value to the given integer type. /// /// - parameter val: The floating value. @@ -1409,29 +1416,7 @@ public class IRBuilder { } } - /// Builds a constant expression that returns the alignment of the given type - /// in bytes. - /// - /// - parameter val: The type to evaluate the alignment of. - /// - /// - returns: An integer value representing the alignment of the given type - /// in bytes. - public func buildAlignOf(_ val: IRType) -> IRValue { - return LLVMAlignOf(val.asLLVM()) - } - - /// Builds a constant expression that returns the size of the given type in - /// bytes. - /// - /// - parameter val: The type to evaluate the size of. - /// - /// - returns: An integer value representing the size of the given type in - /// bytes. - public func buildSizeOf(_ val: IRType) -> IRValue { - return LLVMSizeOf(val.asLLVM()) - } - - /// Builds an expression that returns the difference between two pointer + /// Build an expression that returns the difference between two pointer /// values, dividing out the size of the pointed-to objects. /// /// This is intended to implement C-style pointer subtraction. As such, the @@ -1451,12 +1436,56 @@ public class IRBuilder { ) return LLVMBuildPtrDiff(llvm, lhs.asLLVM(), rhs.asLLVM(), name) } +} + +// MARK: Type Information - // MARK: Atomic Instructions +extension IRBuilder { + /// Build a constant expression that returns the alignment of the given type + /// in bytes. + /// + /// - parameter val: The type to evaluate the alignment of. + /// + /// - returns: An integer value representing the alignment of the given type + /// in bytes. + public func buildAlignOf(_ val: IRType) -> IRValue { + return LLVMAlignOf(val.asLLVM()) + } - /// Builds a fence instruction that introduces "happens-before" edges between + /// Build a constant expression that returns the size of the given type in + /// bytes. + /// + /// - parameter val: The type to evaluate the size of. + /// + /// - returns: An integer value representing the size of the given type in + /// bytes. + public func buildSizeOf(_ val: IRType) -> IRValue { + return LLVMSizeOf(val.asLLVM()) + } +} + +// MARK: Atomic Instructions + +extension IRBuilder { + /// Build a fence instruction that introduces "happens-before" edges between /// operations. /// + /// A fence `A` which has (at least) `release` ordering semantics synchronizes + /// with a fence `B` with (at least) `acquire` ordering semantics if and only + /// if there exist atomic operations X and Y, both operating on some atomic + /// object `M`, such that `A` is sequenced before `X`, `X` modifies `M` + /// (either directly or through some side effect of a sequence headed by `X`), + /// `Y` is sequenced before `B`, and `Y` observes `M`. This provides a + /// happens-before dependency between `A` and `B`. Rather than an explicit + /// fence, one (but not both) of the atomic operations `X` or `Y` might + /// provide a release or acquire (resp.) ordering constraint and still + /// synchronize-with the explicit fence and establish the happens-before edge. + /// + /// A fence which has `sequentiallyConsistent` ordering, in addition to having + /// both `acquire` and `release` semantics specified above, participates in + /// the global program order of other `sequentiallyConsistent` operations + /// and/or fences. + /// /// - parameter ordering: Defines the kind of "synchronizes-with" edge this /// fence adds. /// - parameter singleThreaded: Specifies that the fence only synchronizes @@ -1466,11 +1495,12 @@ public class IRBuilder { /// - parameter name: The name for the newly inserted instruction. /// /// - returns: A value representing `void`. - public func buildFence(ordering: AtomicOrdering, singleThreaded: Bool = false, name: String = "") -> IRValue { + @discardableResult + public func buildFence(ordering: AtomicOrdering, singleThreaded: Bool = false, name: String = "") -> IRInstruction { return LLVMBuildFence(llvm, ordering.llvm, singleThreaded.llvm, name) } - /// Builds an atomic compare-and-exchange instruction to atomically modify + /// Build an atomic compare-and-exchange instruction to atomically modify /// memory. It loads a value in memory and compares it to a given value. If /// they are equal, it tries to store a new value into the memory. /// @@ -1517,7 +1547,7 @@ public class IRBuilder { ) } - /// Builds an atomic read-modify-write instruction to atomically modify memory. + /// Build an atomic read-modify-write instruction to atomically modify memory. /// /// - parameter atomicOp: The atomic operation to perform. /// - parameter ptr: The address of a value to modify. @@ -1537,10 +1567,12 @@ public class IRBuilder { ) -> IRValue { return LLVMBuildAtomicRMW(llvm, atomicOp.llvm, ptr.asLLVM(), value.asLLVM(), ordering.llvm, singleThreaded.llvm) } +} - // MARK: C Standard Library Instructions +// MARK: C Standard Library Instructions - /// Builds a call to the C standard library `malloc` instruction. +extension IRBuilder { + /// Build a call to the C standard library `malloc` instruction. /// ``` /// (type *)malloc(sizeof(type)); /// ``` @@ -1552,10 +1584,10 @@ public class IRBuilder { /// - parameter type: The intended result type being allocated. The result /// of the `malloc` will be a pointer to this type. /// - parameter count: An optional number of slots to allocate, to simulate a - /// C array. This is equivalent to + /// C array. /// - parameter name: The intended name for the `malloc`'d value. public func buildMalloc(_ type: IRType, count: IRValue? = nil, - name: String = "") -> IRValue { + name: String = "") -> IRInstruction { if let count = count { return LLVMBuildArrayMalloc(llvm, type.asLLVM(), count.asLLVM(), name) } else { @@ -1563,19 +1595,121 @@ public class IRBuilder { } } - /// Builds a call to the C standard library `free` function, with the provided + /// Build a call to the C standard library `free` function, with the provided /// pointer. /// /// - parameter ptr: The pointer to `free`. /// - returns: The `free` instruction. @discardableResult - public func buildFree(_ ptr: IRValue) -> IRValue { + public func buildFree(_ ptr: IRValue) -> IRInstruction { return LLVMBuildFree(llvm, ptr.asLLVM()) } +} - // MARK: Aggregate Instructions +// MARK: Memory Intrinsics + +extension IRBuilder { + /// Builds a call to the `llvm.memset.*` family of intrinsics to fill a + /// given block of memory with a given byte value. + /// + /// - NOTE: Unlike the standard function `memset` defined in libc, + /// `llvm.memset` does not return a value and may be volatile. The address + /// space of the source and destination values need not match. + /// + /// - Parameters: + /// - dest: A pointer value to the destination that will be filled. + /// - value: A byte value to fill the destination with. + /// - length: The number of bytes to fill. + /// - alignment: The alignment of the destination pointer value. + /// - volatile: If true, builds a volatile `llvm.memset` intrinsic, else + /// builds a non-volatile `llvm.memset` instrinsic. The exact behavior of + /// volatile memory intrinsics is platform-dependent and should not be + /// relied upon to perform consistently. For more information, see the + /// language reference's section on [Volatile Memory + /// Access](http://llvm.org/docs/LangRef.html#volatile-memory-accesses). + @discardableResult + public func buildMemset( + to dest: IRValue, of value: IRValue, length: IRValue, + alignment: Alignment, volatile: Bool = false + ) -> IRInstruction { + let instruction = LLVMBuildMemSet(self.llvm, dest.asLLVM(), value.asLLVM(), length.asLLVM(), alignment.rawValue)! + LLVMSetVolatile(instruction, volatile.llvm) + return instruction + } + + /// Builds a call to the `llvm.memcpy.*` family of intrinsics to copy a block + /// of memory to a given destination memory location from a given source + /// memory location. + /// + /// - WARNING: It is illegal for the destination and source locations to + /// overlap each other. + /// + /// - NOTE: Unlike the standard function `memcpy` defined in libc, + /// `llvm.memcpy` does not return a value and may be volatile. The address + /// space of the source and destination values need not match. + /// + /// - Parameters: + /// - dest: A pointer to the destination that will be filled. + /// - destAlign: The alignment of the destination pointer value. + /// - src: A pointer to the source that will be copied from. + /// - srcAlign: The alignment of the source pointer value. + /// - length: The number of bytes to fill. + /// - volatile: If true, builds a volatile `llvm.memcpy` intrinsic, else + /// builds a non-volatile `llvm.memcpy` instrinsic. The exact behavior of + /// volatile memory intrinsics is platform-dependent and should not be + /// relied upon to perform consistently. For more information, see the + /// language reference's section on [Volatile Memory + /// Access](http://llvm.org/docs/LangRef.html#volatile-memory-accesses). + @discardableResult + public func buildMemCpy( + to dest: IRValue, _ destAlign: Alignment, + from src: IRValue, _ srcAlign: Alignment, + length: IRValue, volatile: Bool = false + ) -> IRInstruction { + let instruction = LLVMBuildMemCpy(self.llvm, dest.asLLVM(), destAlign.rawValue, src.asLLVM(), srcAlign.rawValue, length.asLLVM())! + LLVMSetVolatile(instruction, volatile.llvm) + return instruction + } + + /// Builds a call to the `llvm.memmove.*` family of intrinsics to move a + /// block of memory to a given destination memory location from a given source + /// memory location. + /// + /// Unlike `llvm.memcpy.*`, the destination and source memory locations may + /// overlap with each other. + /// + /// - NOTE: Unlike the standard function `memmove` defined in libc, + /// `llvm.memmove` does not return a value and may be volatile. The address + /// space of the source and destination values need not match. + /// + /// - Parameters: + /// - dest: A pointer to the destination that will be filled. + /// - destAlign: The alignment of the destination pointer value. + /// - src: A pointer to the source that will be copied from. + /// - srcAlign: The alignment of the source pointer value. + /// - length: The number of bytes to fill. + /// - volatile: If true, builds a volatile `llvm.memmove` intrinsic, else + /// builds a non-volatile `llvm.memmove` instrinsic. The exact behavior of + /// volatile memory intrinsics is platform-dependent and should not be + /// relied upon to perform consistently. For more information, see the + /// language reference's section on [Volatile Memory + /// Access](http://llvm.org/docs/LangRef.html#volatile-memory-accesses). + @discardableResult + public func buildMemMove( + to dest: IRValue, _ destAlign: Alignment, + from src: IRValue, _ srcAlign: Alignment, + length: IRValue, volatile: Bool = false + ) -> IRInstruction { + let instruction = LLVMBuildMemMove(self.llvm, dest.asLLVM(), destAlign.rawValue, src.asLLVM(), srcAlign.rawValue, length.asLLVM())! + LLVMSetVolatile(instruction, volatile.llvm) + return instruction + } +} + +// MARK: Aggregate Instructions - /// Builds an instruction to insert a value into a member field in an +extension IRBuilder { + /// Build an instruction to insert a value into a member field in an /// aggregate value. /// /// - parameter aggregate: A value of array or structure type. @@ -1589,7 +1723,7 @@ public class IRBuilder { return LLVMBuildInsertValue(llvm, aggregate.asLLVM(), element.asLLVM(), UInt32(index), name) } - /// Builds an instruction to extract a value from a member field in an + /// Build an instruction to extract a value from a member field in an /// aggregate value. /// /// An `extract value` instruction differs from a `get element pointer` @@ -1602,13 +1736,15 @@ public class IRBuilder { /// /// - returns: A value representing an aggregate that has been updated with /// the given value at the given index. - func buildExtractValue(aggregate: IRValue, index: Int, name: String = "") -> IRValue { + public func buildExtractValue(aggregate: IRValue, index: Int, name: String = "") -> IRValue { return LLVMBuildExtractValue(llvm, aggregate.asLLVM(), UInt32(index), name) } +} - // MARK: Vector Instructions +// MARK: Vector Instructions - /// Builds a vector insert instruction to nondestructively insert the given +extension IRBuilder { + /// Build a vector insert instruction to nondestructively insert the given /// value into the given vector. /// /// - parameter vector: A value of vector type. @@ -1622,7 +1758,7 @@ public class IRBuilder { return LLVMBuildInsertElement(llvm, vector.asLLVM(), element.asLLVM(), index.asLLVM(), name) } - /// Builds an instruction to extract a single scalar element from a vector at + /// Build an instruction to extract a single scalar element from a vector at /// a specified index. /// /// - parameter vector: A value of vector type. @@ -1634,10 +1770,18 @@ public class IRBuilder { return LLVMBuildExtractElement(llvm, vector.asLLVM(), index.asLLVM(), name) } - /// Builds a vector shuffle instruction to construct a permutation of elements + /// Build a vector shuffle instruction to construct a permutation of elements /// from the two given input vectors, returning a vector with the same element /// type as the inputs and length that is the same as the shuffle mask. /// + /// The elements of the two input vectors are numbered from left to right + /// across both of the vectors. The shuffle mask operand specifies, for each + /// element of the result vector, which element of the two input vectors the + /// result element gets. If the shuffle mask is `undef`, the result vector is + /// also `undef`. If any element of the mask operand is `undef`, that element + /// of the result is `undef`. If the shuffle mask selects an `undef` element + /// from one of the input vectors, the resulting element is `undef`. + /// /// - parameter vector1: The first vector to shuffle. /// - parameter vector2: The second vector to shuffle. /// - parameter mask: A constant vector of `i32` values that acts as a mask @@ -1651,9 +1795,11 @@ public class IRBuilder { } return LLVMBuildShuffleVector(llvm, vector1.asLLVM(), vector2.asLLVM(), mask.asLLVM(), name) } +} - // MARK: Global Variable Instructions +// MARK: Global Variable Instructions +extension IRBuilder { /// Build a named global of the given type. /// /// - parameter name: The name of the newly inserted global value. @@ -1662,14 +1808,8 @@ public class IRBuilder { /// variable resides. /// /// - returns: A value representing the newly inserted global variable. - public func addGlobal(_ name: String, type: IRType, addressSpace: Int? = nil) -> Global { - let llvm: LLVMValueRef - if let addressSpace = addressSpace { - llvm = LLVMAddGlobalInAddressSpace(module.llvm, type.asLLVM(), name, UInt32(addressSpace)) - } else { - llvm = LLVMAddGlobal(module.llvm, type.asLLVM(), name) - } - return Global(llvm: llvm) + public func addGlobal(_ name: String, type: IRType, addressSpace: AddressSpace = .zero) -> Global { + return self.module.addGlobal(name, type: type, addressSpace: addressSpace) } /// Build a named global of the given type. @@ -1680,10 +1820,8 @@ public class IRBuilder { /// variable resides. /// /// - returns: A value representing the newly inserted global variable. - public func addGlobal(_ name: String, initializer: IRValue, addressSpace: Int? = nil) -> Global { - var global = addGlobal(name, type: initializer.type) - global.initializer = initializer - return global + public func addGlobal(_ name: String, initializer: IRValue, addressSpace: AddressSpace = .zero) -> Global { + return self.module.addGlobal(name, initializer: initializer, addressSpace: addressSpace) } /// Build a named global string consisting of an array of `i8` type filled in @@ -1694,18 +1832,10 @@ public class IRBuilder { /// /// - returns: A value representing the newly inserted global string variable. public func addGlobalString(name: String, value: String) -> Global { - let length = value.utf8.count - - var global = addGlobal(name, type: - ArrayType(elementType: IntType.int8, count: length + 1)) - - global.alignment = 1 - global.initializer = value - - return global + return self.module.addGlobalString(name: name, value: value) } - /// Builds a named global variable containing the characters of the given + /// Build a named global variable containing the characters of the given /// string value as an array of `i8` type filled in with the nul terminated /// string value. /// @@ -1717,7 +1847,7 @@ public class IRBuilder { return Global(llvm: LLVMBuildGlobalString(llvm, string, name)) } - /// Builds a named global variable containing a pointer to the contents of the + /// Build a named global variable containing a pointer to the contents of the /// given string value. /// /// - parameter string: The character contents of the newly inserted global. @@ -1729,7 +1859,7 @@ public class IRBuilder { return LLVMBuildGlobalStringPtr(llvm, string, name) } - /// Builds a named alias to a global value or a constant expression. + /// Build a named alias to a global value or a constant expression. /// /// Aliases, unlike function or variables, don’t create any new data. They are /// just a new symbol and metadata for an existing position. @@ -1740,12 +1870,14 @@ public class IRBuilder { /// /// - returns: A value representing the newly created alias. public func addAlias(name: String, to aliasee: IRGlobal, type: IRType) -> Alias { - return Alias(llvm: LLVMAddAlias(module.llvm, type.asLLVM(), aliasee.asLLVM(), name)) + return self.module.addAlias(name: name, to: aliasee, type: type) } +} - // MARK: Inline Assembly +// MARK: Inline Assembly - /// Builds a value representing an inline assembly expression (as opposed to +extension IRBuilder { + /// Build a value representing an inline assembly expression (as opposed to /// module-level inline assembly). /// /// LLVM represents inline assembler as a template string (containing the @@ -1781,15 +1913,114 @@ public class IRBuilder { /// /// - returns: A representation of the newly created inline assembly /// expression. - public func buildInlineAssembly(_ asm: String, type: FunctionType, constraints: String = "", hasSideEffects: Bool = true, needsAlignedStack: Bool = true) -> IRValue { - return LLVMConstInlineAsm(type.asLLVM(), asm, constraints, hasSideEffects.llvm, needsAlignedStack.llvm) + public func buildInlineAssembly( + _ asm: String, dialect: InlineAssemblyDialect, type: FunctionType, + constraints: String = "", + hasSideEffects: Bool = true, needsAlignedStack: Bool = true + ) -> IRValue { + var asm = asm.utf8CString + var constraints = constraints.utf8CString + return asm.withUnsafeMutableBufferPointer { asm in + return constraints.withUnsafeMutableBufferPointer { constraints in + return LLVMGetInlineAsm(type.asLLVM(), + asm.baseAddress, asm.count, + constraints.baseAddress, constraints.count, + hasSideEffects.llvm, needsAlignedStack.llvm, + dialect.llvm) + } + } } +} - deinit { - LLVMDisposeBuilder(llvm) +// MARK: Deprecated APIs + +extension IRBuilder { + /// Build a load instruction that loads a value from the location in the + /// given value. + /// + /// If alignment is not specified, or if zero, the target will choose a default + /// value that is convenient and compatible with the type. + /// + /// - parameter ptr: The pointer value to load from. + /// - parameter ordering: The ordering effect of the fence for this load, + /// if any. Defaults to a nonatomic load. + /// - parameter volatile: Whether this is a load from a volatile memory location. + /// - parameter alignment: The alignment of the access. + /// - parameter name: The name for the newly inserted instruction. + /// + /// - returns: A value representing the result of a load from the given + /// pointer value. + @available(*, deprecated, message: "Use buildLoad(_:type:ordering:volatile:alignment:name) instead") + public func buildLoad(_ ptr: IRValue, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false, alignment: Alignment = .zero, name: String = "") -> IRInstruction { + let loadInst = LLVMBuildLoad(llvm, ptr.asLLVM(), name)! + LLVMSetOrdering(loadInst, ordering.llvm) + LLVMSetVolatile(loadInst, volatile.llvm) + if !alignment.isZero { + LLVMSetAlignment(loadInst, alignment.rawValue) + } + return loadInst + } + + /// Build a GEP (Get Element Pointer) instruction suitable for indexing into + /// a struct. + /// + /// - parameter ptr: The base address for the index calculation. + /// - parameter index: The offset from the base for the index calculation. + /// - parameter name: The name for the newly inserted instruction. + /// + /// - returns: A value representing the address of a subelement of the given + /// struct value. + @available(*, deprecated, message: "Use buildStructGEP(_:type:index:name) instead") + public func buildStructGEP(_ ptr: IRValue, index: Int, name: String = "") -> IRValue { + return LLVMBuildStructGEP(llvm, ptr.asLLVM(), UInt32(index), name) + } + + /// Build a GEP (Get Element Pointer) instruction. + /// + /// The `GEP` instruction is often the source of confusion. LLVM [provides a + /// document](http://llvm.org/docs/GetElementPtr.html) to answer questions + /// around its semantics and correct usage. + /// + /// - parameter ptr: The base address for the index calculation. + /// - parameter indices: A list of indices that indicate which of the elements + /// of the aggregate object are indexed. + /// - parameter name: The name for the newly inserted instruction. + /// + /// - returns: A value representing the address of a subelement of the given + /// aggregate data structure value. + @available(*, deprecated, message: "Use buildGEP(_:type:indices:name) instead") + public func buildGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue { + var vals = indices.map { $0.asLLVM() as Optional } + return vals.withUnsafeMutableBufferPointer { buf in + return LLVMBuildGEP(llvm, ptr.asLLVM(), buf.baseAddress, UInt32(buf.count), name) + } + } + + /// Build a `GEP` (Get Element Pointer) instruction with a resultant value + /// that is undefined if the address is outside the actual underlying + /// allocated object and not the address one-past-the-end. + /// + /// The `GEP` instruction is often the source of confusion. LLVM [provides a + /// document](http://llvm.org/docs/GetElementPtr.html) to answer questions + /// around its semantics and correct usage. + /// + /// - parameter ptr: The base address for the index calculation. + /// - parameter indices: A list of indices that indicate which of the elements + /// of the aggregate object are indexed. + /// - parameter name: The name for the newly inserted instruction. + /// + /// - returns: A value representing the address of a subelement of the given + /// aggregate data structure value. + @available(*, deprecated, message: "Use buildInBoundsGEP(_:type:indices:name) instead") + public func buildInBoundsGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue { + var vals = indices.map { $0.asLLVM() as Optional } + return vals.withUnsafeMutableBufferPointer { buf in + return LLVMBuildInBoundsGEP(llvm, ptr.asLLVM(), buf.baseAddress, UInt32(buf.count), name) + } } } + private func lowerVector(_ type: IRType) -> IRType { guard let vectorType = type as? VectorType else { return type diff --git a/Sources/LLVM/IRGlobal.swift b/Sources/LLVM/IRGlobal.swift index ac46f321..9848cf37 100644 --- a/Sources/LLVM/IRGlobal.swift +++ b/Sources/LLVM/IRGlobal.swift @@ -1,16 +1,25 @@ #if SWIFT_PACKAGE import cllvm +import llvmshims #endif /// An `IRGlobal` is a value, alias, or function that exists at the top level of /// an LLVM module. -public protocol IRGlobal: IRValue {} +public protocol IRGlobal: IRConstant {} extension IRGlobal { + /// Retrieves the "value type" of this global value. + /// + /// The formal type of a global value is always a pointer type. The value + /// type, in contrast, is the type of the value the global points to. + public var valueType: IRType { + return convertType(LLVMGlobalGetValueType(asLLVM())) + } + /// Retrieves the alignment of this value. - public var alignment: Int { - get { return Int(LLVMGetAlignment(asLLVM())) } - set { LLVMSetAlignment(asLLVM(), UInt32(newValue)) } + public var alignment: Alignment { + get { return Alignment(LLVMGetAlignment(asLLVM())) } + set { LLVMSetAlignment(asLLVM(), newValue.rawValue) } } /// Retrieves the linkage information for this global. @@ -31,4 +40,51 @@ extension IRGlobal { get { return StorageClass(llvm: LLVMGetDLLStorageClass(asLLVM())) } set { LLVMSetDLLStorageClass(asLLVM(), newValue.llvm) } } + + /// Retrieves an indicator for the significance of a global value's address. + public var unnamedAddressKind: UnnamedAddressKind { + get { return UnnamedAddressKind(llvm: LLVMGetUnnamedAddress(asLLVM())) } + set { LLVMSetUnnamedAddress(asLLVM(), newValue.llvm) } + } + + /// Retrieves the COMDAT section for this global, if it exists. + public var comdat: Comdat? { + get { return LLVMGetComdat(asLLVM()).map(Comdat.init(llvm:)) } + set { LLVMSetComdat(asLLVM(), newValue?.llvm) } + } + + /// Retrieves the section associated with the symbol that will eventually be + /// emitted for this global value. + /// + /// - Note: Global `Alias` values may or may not be resolvable to any + /// particular section given the state of the IR in an arbitrary module. A + /// return value of the empty string indicates a failed section lookup. + public var section: String { + get { + guard let sname = LLVMGetSection(asLLVM()) else { return "" } + return String(cString: sname) + } + set { LLVMSetSection(asLLVM(), newValue) } + } + + /// Retrieves a global unique identifier for this global value. + /// + /// This is a 64 bits hash that is used by PGO and ThinLTO to have a compact + /// unique way to identify a symbol. + public var guid: UInt64 { + return LLVMGlobalGetGUID(self.asLLVM()) + } + + /// Removes this global value from the module and deallocates it. + /// + /// - note: To ensure correct removal of the global value, you must invalidate + /// any references to it - usually by performing an + /// "Replace All Uses With" (RAUW) operation. + /// + /// - warning: The native Swift object wrapping this global becomes a dangling + /// reference once this function has been invoked. It is + /// recommended that all references to it be dropped immediately. + public func eraseFromParent() { + LLVMDeleteGlobal(self.asLLVM()) + } } diff --git a/Sources/LLVM/IRMetadata.swift b/Sources/LLVM/IRMetadata.swift new file mode 100644 index 00000000..3559fb09 --- /dev/null +++ b/Sources/LLVM/IRMetadata.swift @@ -0,0 +1,643 @@ +#if SWIFT_PACKAGE +import cllvm +import llvmshims +#endif + +/// An unfortunate artifact of the design of the metadata class hierarchy is +/// that you may find it convenient to force-cast metadata nodes. In general, +/// this behavior is not encouraged, but it will be supported for now. +public protocol _IRMetadataInitializerHack { + /// Initialize a metadata node from a raw LLVM metadata ref. + init(llvm: LLVMMetadataRef) +} + +/// The `Metadata` protocol captures those types that represent metadata nodes +/// in LLVM IR. +/// +/// LLVM IR allows metadata to be attached to instructions in the program that +/// can convey extra information about the code to the optimizers and code +/// generator. One example application of metadata is source-level debug +/// information. +/// +/// Metadata does not have a type, and is not a value. If referenced from a call +/// instruction, it uses the metadata type. +/// +/// Debug Information +/// ================= +/// +/// The idea of LLVM debugging information is to capture how the important +/// pieces of the source-language’s Abstract Syntax Tree map onto LLVM code. +/// LLVM takes a number of positions on the impact of the broader compilation +/// process on debug information: +/// +/// - Debugging information should have very little impact on the rest of the +/// compiler. No transformations, analyses, or code generators should need to +/// be modified because of debugging information. +/// - LLVM optimizations should interact in well-defined and easily described +/// ways with the debugging information. +/// - Because LLVM is designed to support arbitrary programming languages, +/// LLVM-to-LLVM tools should not need to know anything about the semantics +/// of the source-level-language. +/// - Source-level languages are often widely different from one another. LLVM +/// should not put any restrictions of the flavor of the source-language, and +/// the debugging information should work with any language. +/// - With code generator support, it should be possible to use an LLVM compiler +/// to compile a program to native machine code and standard debugging +/// formats. This allows compatibility with traditional machine-code level +/// debuggers, like GDB, DBX, or CodeView. +public protocol IRMetadata: _IRMetadataInitializerHack { + /// Retrieves the underlying LLVM metadata object. + func asMetadata() -> LLVMMetadataRef +} + +extension IRMetadata { + /// Replaces all uses of the this metadata with the given metadata. + /// + /// - parameter metadata: The new value to swap in. + public func replaceAllUses(with metadata: IRMetadata) { + LLVMMetadataReplaceAllUsesWith(self.asMetadata(), metadata.asMetadata()) + } +} + +extension IRMetadata { + /// Dumps a representation of this metadata to stderr. + public func dump() { + LLVMDumpValue(LLVMMetadataAsValue(LLVMGetGlobalContext(), self.asMetadata())) + } + + /// Force-casts metadata to a destination type. + /// + /// - warning: In general, use of this method is discouraged and can + /// lead to unpredictable results or undefined behavior. No checks are + /// performed before, during, or after the cast. + public func forceCast(to: DestTy.Type) -> DestTy { + return DestTy(llvm: self.asMetadata()) + } + + /// Returns the kind of this metadata node. + public var kind: IRMetadataKind { + return IRMetadataKind(raw: LLVMGetMetadataKind(self.asMetadata())) + } +} + +/// Denotes a scope in which child metadata nodes can be inserted. +public protocol DIScope: IRMetadata {} + +extension DIScope { + /// Retrieves the file metadata associated with this scope, if any. + public var file: FileMetadata? { + return LLVMDIScopeGetFile(self.asMetadata()).map(FileMetadata.init(llvm:)) + } +} + +/// Denotes metadata for a type. +public protocol DIType: DIScope {} + +extension DIType { + /// Retrieves the name of this type. + public var name: String { + var length: Int = 0 + let cstring = LLVMDITypeGetName(self.asMetadata(), &length) + return String(cString: cstring!) + } + + /// Retrieves the size of the type represented by this metadata in bits. + public var sizeInBits: Size { + return Size(LLVMDITypeGetSizeInBits(self.asMetadata())) + } + + /// Retrieves the offset of the type represented by this metadata in bits. + public var offsetInBits: Size { + return Size(LLVMDITypeGetOffsetInBits(self.asMetadata())) + } + + /// Retrieves the alignment of the type represented by this metadata in bits. + public var alignmentInBits: Alignment { + return Alignment(LLVMDITypeGetAlignInBits(self.asMetadata())) + } + + /// Retrieves the line the type represented by this metadata is declared on. + public var line: Int { + return Int(LLVMDITypeGetLine(self.asMetadata())) + } + + /// Retrieves the flags the type represented by this metadata is declared + /// with. + public var flags: DIFlags { + return DIFlags(rawValue: LLVMDITypeGetFlags(self.asMetadata()).rawValue) + } +} + +/// A `DebugLocation` represents a location in source. +/// +/// Debug locations are de-duplicated by file and line. If more than one +/// location inside a given scope needs to share a line, a discriminator value +/// must be set or those locations will be considered equivalent. +public struct DebugLocation: IRMetadata { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + /// Retrieves the line described by this location. + public var line: Int { + return Int(LLVMDILocationGetLine(self.llvm)) + } + + /// Retrieves the column described by this location. + public var column: Int { + return Int(LLVMDILocationGetColumn(self.llvm)) + } + + /// Retrieves the enclosing scope containing this location. + public var scope: DIScope { + return DIOpaqueType(llvm: LLVMDILocationGetScope(self.llvm)) + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +struct AnyMetadata: IRMetadata { + let llvm: LLVMMetadataRef + + func asMetadata() -> LLVMMetadataRef { + return llvm + } +} + +struct DIOpaqueType: DIType { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// `CompileUnitMetadata` nodes represent a compile unit, the root of a metadata +/// hierarchy for a translation unit. +/// +/// Compile unit descriptors provide the root scope for objects declared in a +/// specific compilation unit. `FileMetadata` descriptors are defined using this +/// scope. +/// +/// These descriptors are collected by a named metadata node `!llvm.dbg.cu`. +/// They keep track of global variables, type information, and imported entities +/// (declarations and namespaces). +public struct CompileUnitMetadata: DIScope { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + + +/// `FileMetadata` nodes represent files. +/// +/// The file name does not necessarily have to be a proper file path. For +/// example, it can include additional slash-separated path components. +public struct FileMetadata: DIScope { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } + + /// Retrieves the name of this file + public var name: String { + var length: UInt32 = 0 + let cstring = LLVMDIFileGetFilename(self.asMetadata(), &length) + return String(cString: cstring!) + } + + /// Retrieves the directory of this file + public var directory: String { + var length: UInt32 = 0 + let cstring = LLVMDIFileGetDirectory(self.asMetadata(), &length) + return String(cString: cstring!) + } + + /// Retrieves the source text of this file. + public var source: String { + var length: UInt32 = 0 + let cstring = LLVMDIFileGetSource(self.asMetadata(), &length) + return String(cString: cstring!) + } +} + +/// `DIBasicType` nodes represent primitive types, such as `int`, `bool` and +/// `float`. +/// +/// Basic types carry an encoding describing the details of the type to +/// influence how it is presented in debuggers. LLVM currently supports +/// specific DWARF "Attribute Type Encodings" that are enumerated in +/// `DIAttributeTypeEncoding`. +public struct DIBasicType: DIType { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// `DISubroutineType` nodes represent subroutine types. +/// +/// Subroutine types are meant to mirror their formal declarations in source: +/// arguments are represented in order. The return type is optional and meant +/// to represent the concept of `void` in C-like languages. +public struct DISubroutineType: DIType { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// `LexicalBlockMetadata` nodes describe nested blocks within a subprogram. The +/// line number and column numbers are used to distinguish two lexical blocks at +/// same depth. +/// +/// Usually lexical blocks are distinct to prevent node merging based on +/// operands. +public struct LexicalBlockMetadata: DIScope { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// `LexicalBlockFile` nodes are used to discriminate between sections of a +/// lexical block. The file field can be changed to indicate textual inclusion, +/// or the discriminator field can be used to discriminate between control flow +/// within a single block in the source language. +public struct LexicalBlockFileMetadata: DIScope { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// `LocalVariableMetadata` nodes represent local variables and function +/// parameters in the source language. +public struct LocalVariableMetadata: IRMetadata { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// `ObjectiveCPropertyMetadata` nodes represent Objective-C property nodes. +public struct ObjectiveCPropertyMetadata: IRMetadata { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// `ImportedEntityMetadata` nodes represent entities (such as modules) imported +/// into a compile unit. +public struct ImportedEntityMetadata: DIType { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// `NameSpaceMetadata` nodes represent subroutines in the source program. +/// They are attached to corresponding LLVM IR functions. +public struct FunctionMetadata: DIScope { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// `NameSpaceMetadata` nodes represent entities like C++ modules. +public struct ModuleMetadata: DIScope { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// `NameSpaceMetadata` nodes represent entities like C++ namespaces. +public struct NameSpaceMetadata: DIScope { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// `MDString` nodes represent string constants in metadata nodes. +public struct MDString: IRMetadata, ExpressibleByStringLiteral { + public typealias StringLiteralType = String + + private let llvm: LLVMMetadataRef + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } + + /// Create an `MDString` node from the given string value. + /// + /// - Parameters: + /// - value: The string value to assign to this metadata node. + public init(_ value: String) { + self.llvm = LLVMValueAsMetadata(LLVMMDString(value, UInt32(value.count))) + } + + public init(stringLiteral value: String) { + self.llvm = LLVMValueAsMetadata(LLVMMDString(value, UInt32(value.count))) + } + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } +} + +/// `MDNode` objects represent generic nodes in a metadata graph. +/// +/// A metadata node is a tuple of references to other metadata. In general, +/// metadata graphs are acyclic and terminate in metadata nodes without +/// operands. +public struct MDNode: IRMetadata { + private let llvm: LLVMMetadataRef + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } + + /// Create a metadata node in the given context with the given operands. + /// + /// - Parameters: + /// - context: The context to allocate the node in. + /// - operands: The operands to attach to the metadata node. + public init(in context: Context = .global, operands: [IRMetadata]) { + var operands = operands.map { $0.asMetadata() as Optional } + self.llvm = operands.withUnsafeMutableBufferPointer { buf in + return LLVMMDNodeInContext2(context.llvm, buf.baseAddress!, buf.count) + } + } + + /// Create a metadata node with the value of a given constant. + /// + /// - Parameters: + /// - constant: The constant value to attach to the node. + public init(constant: IRConstant) { + self.llvm = LLVMValueAsMetadata(constant.asLLVM()) + } + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } +} + +/// Represents a temporary metadata node. +/// +/// Temporary metadata nodes aid in the construction of cyclic metadata. The +/// typical construction pattern is usually as follows: +/// +/// // Allocate a temporary temp node +/// let temp = TemporaryMDNode(in: context, operands: []) +/// // Prepare the operands to the metadata node... +/// var ops = [IRMetadata]() +/// // ... +/// // Create the real node +/// let root = MDNode(in: context, operands: ops) +/// +/// At this point we have the following metadata structure: +/// +/// // !0 = metadata !{} <- temp +/// // !1 = metadata !{metadata !0} <- root +/// // Replace the temp operand with the root node +/// +/// The knot is tied by RAUW'ing the temporary node: +/// +/// temp.replaceAllUses(with: root) +/// // We now have +/// // !1 = metadata !{metadata !1} <- self-referential root +/// +/// - Warning: It is critical that temporary metadata nodes be "RAUW'd" +/// (replace-all-uses-with) before the metadata graph is finalized. After +/// that time, all remaining temporary metadata nodes will become unresolved +/// metadata. +public class TemporaryMDNode: IRMetadata { + private let llvm: LLVMMetadataRef + + required public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } + + /// Create a new temporary metadata node in the given context with the + /// given operands. + /// + /// - Parameters: + /// - context: The context to allocate the node in. + /// - operands: The operands to attach to the metadata node. + public init(in context: Context = .global, operands: [IRMetadata]) { + var operands = operands.map { $0.asMetadata() as Optional } + self.llvm = operands.withUnsafeMutableBufferPointer { buf in + return LLVMTemporaryMDNode(context.llvm, buf.baseAddress!, buf.count) + } + } + + /// Deinitialize this value and dispose of its resources. + deinit { + LLVMDisposeTemporaryMDNode(self.llvm) + } + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } +} + +/// `ExpressionMetadata` nodes represent expressions that are inspired by the +/// DWARF expression language. They are used in debug intrinsics (such as +/// llvm.dbg.declare and llvm.dbg.value) to describe how the referenced LLVM +/// variable relates to the source language variable. +/// +/// Debug intrinsics are interpreted left-to-right: start by pushing the +/// value/address operand of the intrinsic onto a stack, then repeatedly push +/// and evaluate opcodes from the `ExpressionMetadata` until the final variable +/// description is produced. +/// +/// Though DWARF supports hundreds of expressions, LLVM currently implements +/// a very limited subset. +public struct ExpressionMetadata: IRMetadata { + internal let llvm: LLVMMetadataRef + + public func asMetadata() -> LLVMMetadataRef { + return llvm + } + + public init(llvm: LLVMMetadataRef) { + self.llvm = llvm + } +} + +/// Enumerates the kind of metadata nodes. +public enum IRMetadataKind { + /// The metadata is a string. + case mdString + /// The metadata is a constant-as-metadata node. + case constantAsMetadata + /// The metadata is a local-as-metadata node. + case localAsMetadata + /// The metadata is a disctint metadata operand placeholder. + case distinctMDOperandPlaceholder + /// The metadata is a tuple. + case mdTuple + /// The metadata is a location. + case location + /// The metadata is an expression. + case expression + /// The metadata is a global variable expression. + case globalVariableExpression + /// The metadata is a generic DI node. + case genericDINode + /// The metadata is a subrange. + case subrange + /// The metadata is an enumerator. + case enumerator + /// The metadata is a basic type. + case basicType + /// The metadata is a derived type. + case derivedType + /// The metadata is a composite type. + case compositeType + /// The metadata is a subroutine type. + case subroutineType + /// The metadata is a file. + case file + /// The metadata is a compile unit. + case compileUnit + /// The metadata is a subprogram. + case subprogram + /// The metadata is a lexical block. + case lexicalBlock + /// The metadata is a lexical block file. + case lexicalBlockFile + /// The metadata is a namespace. + case namespace + /// The metadata is a module. + case module + /// The metadata is a template type parameter. + case templateTypeParameter + /// The metadata is a template value parameter. + case templateValueParameter + /// The metadata is a global variable. + case globalVariable + /// The metadata is a local variable. + case localVariable + /// The metadata is a label. + case label + /// The metadata is an Objective-C property. + case objCProperty + /// The metadata is an imported entity. + case importedEntity + /// The metadata is a macro. + case macro + /// The metadata is a macro file. + case macroFile + + fileprivate init(raw: LLVMMetadataKind) { + switch Int(raw) { + case LLVMMDStringMetadataKind: self = .mdString + case LLVMConstantAsMetadataMetadataKind: self = .constantAsMetadata + case LLVMLocalAsMetadataMetadataKind: self = .localAsMetadata + case LLVMDistinctMDOperandPlaceholderMetadataKind: self = .distinctMDOperandPlaceholder + case LLVMMDTupleMetadataKind: self = .mdTuple + case LLVMDILocationMetadataKind: self = .location + case LLVMDIExpressionMetadataKind: self = .expression + case LLVMDIGlobalVariableExpressionMetadataKind: self = .globalVariableExpression + case LLVMGenericDINodeMetadataKind: self = .genericDINode + case LLVMDISubrangeMetadataKind: self = .subrange + case LLVMDIEnumeratorMetadataKind: self = .enumerator + case LLVMDIBasicTypeMetadataKind: self = .basicType + case LLVMDIDerivedTypeMetadataKind: self = .derivedType + case LLVMDICompositeTypeMetadataKind: self = .compositeType + case LLVMDISubroutineTypeMetadataKind: self = .subroutineType + case LLVMDIFileMetadataKind: self = .file + case LLVMDICompileUnitMetadataKind: self = .compileUnit + case LLVMDISubprogramMetadataKind: self = .subprogram + case LLVMDILexicalBlockMetadataKind: self = .lexicalBlock + case LLVMDILexicalBlockFileMetadataKind: self = .lexicalBlockFile + case LLVMDINamespaceMetadataKind: self = .namespace + case LLVMDIModuleMetadataKind: self = .module + case LLVMDITemplateTypeParameterMetadataKind: self = .templateTypeParameter + case LLVMDITemplateValueParameterMetadataKind: self = .templateValueParameter + case LLVMDIGlobalVariableMetadataKind: self = .globalVariable + case LLVMDILocalVariableMetadataKind: self = .localVariable + case LLVMDILabelMetadataKind: self = .label + case LLVMDIObjCPropertyMetadataKind: self = .objCProperty + case LLVMDIImportedEntityMetadataKind: self = .importedEntity + case LLVMDIMacroMetadataKind: self = .macro + case LLVMDIMacroFileMetadataKind: self = .macroFile + default: + fatalError("Unknown kind") + } + } +} diff --git a/Sources/LLVM/IRType.swift b/Sources/LLVM/IRType.swift index ae6bcc7d..a77b1982 100644 --- a/Sources/LLVM/IRType.swift +++ b/Sources/LLVM/IRType.swift @@ -11,8 +11,8 @@ public protocol IRType { public extension IRType { /// Returns the special `null` value for this type. - public func null() -> IRValue { - return LLVMConstNull(asLLVM()) + func null() -> IRConstant { + return Constant(llvm: LLVMConstNull(asLLVM())) } /// Returns the special LLVM `undef` value for this type. @@ -20,20 +20,29 @@ public extension IRType { /// The `undef` value can be used anywhere a constant is expected, and /// indicates that the user of the value may receive an unspecified /// bit-pattern. - public func undef() -> IRValue { + func undef() -> IRValue { return LLVMGetUndef(asLLVM()) } /// Returns the special LLVM constant `null` pointer value for this type /// initialized to `null`. - public func constPointerNull() -> IRValue { - return LLVMConstPointerNull(asLLVM()) + func constPointerNull() -> IRConstant { + return Constant(llvm: LLVMConstPointerNull(asLLVM())) } /// Returns the context associated with this type - public var context: Context { + var context: Context { return Context(llvm: LLVMGetTypeContext(asLLVM())) } + + /// If this is a vector type, return the element type, otherwise + /// return `self`. + var scalarType: IRType { + guard let vecTy = self as? VectorType else { + return self + } + return vecTy.elementType + } } internal func convertType(_ type: LLVMTypeRef) -> IRType { @@ -62,7 +71,7 @@ internal func convertType(_ type: LLVMTypeRef) -> IRType { } let ret = convertType(LLVMGetReturnType(type)) let isVarArg = LLVMIsFunctionVarArg(type) != 0 - return FunctionType(argTypes: params, returnType: ret, isVarArg: isVarArg) + return FunctionType(params, ret, variadic: isVarArg) case LLVMStructTypeKind: return StructType(llvm: type) case LLVMArrayTypeKind: @@ -72,7 +81,7 @@ internal func convertType(_ type: LLVMTypeRef) -> IRType { case LLVMPointerTypeKind: let pointee = convertType(LLVMGetElementType(type)) let addressSpace = Int(LLVMGetPointerAddressSpace(type)) - return PointerType(pointee: pointee, addressSpace: addressSpace) + return PointerType(pointee: pointee, addressSpace: AddressSpace(addressSpace)) case LLVMVectorTypeKind: let elementType = convertType(LLVMGetElementType(type)) let count = Int(LLVMGetVectorSize(type)) diff --git a/Sources/LLVM/IRValue+Kinds.swift b/Sources/LLVM/IRValue+Kinds.swift index 30e73b35..72f0b461 100644 --- a/Sources/LLVM/IRValue+Kinds.swift +++ b/Sources/LLVM/IRValue+Kinds.swift @@ -7,392 +7,392 @@ import cllvm public extension IRValue { /// Whether or not the underlying LLVM value is an `Argument` - public var isAArgument: Bool { + var isAArgument: Bool { return LLVMIsAArgument(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `BasicBlock` - public var isABasicBlock: Bool { + var isABasicBlock: Bool { return LLVMIsABasicBlock(asLLVM()) != nil } /// Whether or not the underlying LLVM value is `InlineAsm` - public var isAInlineAsm: Bool { + var isAInlineAsm: Bool { return LLVMIsAInlineAsm(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `User` - public var isAUser: Bool { + var isAUser: Bool { return LLVMIsAUser(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `Constant` - public var isAConstant: Bool { + var isAConstant: Bool { return LLVMIsAConstant(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `BlockAddress` - public var isABlockAddress: Bool { + var isABlockAddress: Bool { return LLVMIsABlockAddress(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantAggregateZero` - public var isAConstantAggregateZero: Bool { + var isAConstantAggregateZero: Bool { return LLVMIsAConstantAggregateZero(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantArray` - public var isAConstantArray: Bool { + var isAConstantArray: Bool { return LLVMIsAConstantArray(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantDataSequential` - public var isAConstantDataSequential: Bool { + var isAConstantDataSequential: Bool { return LLVMIsAConstantDataSequential(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantDataArray` - public var isAConstantDataArray: Bool { + var isAConstantDataArray: Bool { return LLVMIsAConstantDataArray(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantDataVector` - public var isAConstantDataVector: Bool { + var isAConstantDataVector: Bool { return LLVMIsAConstantDataVector(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantExpr` - public var isAConstantExpr: Bool { + var isAConstantExpr: Bool { return LLVMIsAConstantExpr(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantFP` - public var isAConstantFP: Bool { + var isAConstantFP: Bool { return LLVMIsAConstantFP(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantInt` - public var isAConstantInt: Bool { + var isAConstantInt: Bool { return LLVMIsAConstantInt(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantPointerNull` - public var isAConstantPointerNull: Bool { + var isAConstantPointerNull: Bool { return LLVMIsAConstantPointerNull(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantStruct` - public var isAConstantStruct: Bool { + var isAConstantStruct: Bool { return LLVMIsAConstantStruct(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantTokenNone` - public var isAConstantTokenNone: Bool { + var isAConstantTokenNone: Bool { return LLVMIsAConstantTokenNone(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ConstantVector` - public var isAConstantVector: Bool { + var isAConstantVector: Bool { return LLVMIsAConstantVector(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `GlobalValue` - public var isAGlobalValue: Bool { + var isAGlobalValue: Bool { return LLVMIsAGlobalValue(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `GlobalAlias` - public var isAGlobalAlias: Bool { + var isAGlobalAlias: Bool { return LLVMIsAGlobalAlias(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `GlobalObject` - public var isAGlobalObject: Bool { + var isAGlobalObject: Bool { return LLVMIsAGlobalObject(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `Function` - public var isAFunction: Bool { + var isAFunction: Bool { return LLVMIsAFunction(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `GlobalVariable` - public var isAGlobalVariable: Bool { + var isAGlobalVariable: Bool { return LLVMIsAGlobalVariable(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `UndefValue` - public var isAUndefValue: Bool { + var isAUndefValue: Bool { return LLVMIsAUndefValue(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `Instruction` - public var isAInstruction: Bool { + var isAInstruction: Bool { return LLVMIsAInstruction(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `BinaryOperator` - public var isABinaryOperator: Bool { + var isABinaryOperator: Bool { return LLVMIsABinaryOperator(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `CallInst` - public var isACallInst: Bool { + var isACallInst: Bool { return LLVMIsACallInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `IntrinsicInst` - public var isAIntrinsicInst: Bool { + var isAIntrinsicInst: Bool { return LLVMIsAIntrinsicInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `DbgInfoIntrinsic` - public var isADbgInfoIntrinsic: Bool { + var isADbgInfoIntrinsic: Bool { return LLVMIsADbgInfoIntrinsic(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `DbgDeclareInst` - public var isADbgDeclareInst: Bool { + var isADbgDeclareInst: Bool { return LLVMIsADbgDeclareInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `MemIntrinsic` - public var isAMemIntrinsic: Bool { + var isAMemIntrinsic: Bool { return LLVMIsAMemIntrinsic(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `MemCpyInst` - public var isAMemCpyInst: Bool { + var isAMemCpyInst: Bool { return LLVMIsAMemCpyInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `MemMoveInst` - public var isAMemMoveInst: Bool { + var isAMemMoveInst: Bool { return LLVMIsAMemMoveInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `MemSetInst` - public var isAMemSetInst: Bool { + var isAMemSetInst: Bool { return LLVMIsAMemSetInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `CmpInst` - public var isACmpInst: Bool { + var isACmpInst: Bool { return LLVMIsACmpInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `FCmpInst` - public var isAFCmpInst: Bool { + var isAFCmpInst: Bool { return LLVMIsAFCmpInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `ICmpInst` - public var isAICmpInst: Bool { + var isAICmpInst: Bool { return LLVMIsAICmpInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `ExtractElementInst` - public var isAExtractElementInst: Bool { + var isAExtractElementInst: Bool { return LLVMIsAExtractElementInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `GetElementPtrInst` - public var isAGetElementPtrInst: Bool { + var isAGetElementPtrInst: Bool { return LLVMIsAGetElementPtrInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `InsertElementInst` - public var isAInsertElementInst: Bool { + var isAInsertElementInst: Bool { return LLVMIsAInsertElementInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `InsertValueInst` - public var isAInsertValueInst: Bool { + var isAInsertValueInst: Bool { return LLVMIsAInsertValueInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `LandingPadInst` - public var isALandingPadInst: Bool { + var isALandingPadInst: Bool { return LLVMIsALandingPadInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `PHINode` - public var isAPHINode: Bool { + var isAPHINode: Bool { return LLVMIsAPHINode(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `SelectInst` - public var isASelectInst: Bool { + var isASelectInst: Bool { return LLVMIsASelectInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ShuffleVectorInst` - public var isAShuffleVectorInst: Bool { + var isAShuffleVectorInst: Bool { return LLVMIsAShuffleVectorInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `StoreInst` - public var isAStoreInst: Bool { + var isAStoreInst: Bool { return LLVMIsAStoreInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `TerminatorInst` - public var isATerminatorInst: Bool { + var isATerminatorInst: Bool { return LLVMIsATerminatorInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `BranchInst` - public var isABranchInst: Bool { + var isABranchInst: Bool { return LLVMIsABranchInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `IndirectBrInst` - public var isAIndirectBrInst: Bool { + var isAIndirectBrInst: Bool { return LLVMIsAIndirectBrInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `InvokeInst` - public var isAInvokeInst: Bool { + var isAInvokeInst: Bool { return LLVMIsAInvokeInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ReturnInst` - public var isAReturnInst: Bool { + var isAReturnInst: Bool { return LLVMIsAReturnInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `SwitchInst` - public var isASwitchInst: Bool { + var isASwitchInst: Bool { return LLVMIsASwitchInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `UnreachableInst` - public var isAUnreachableInst: Bool { + var isAUnreachableInst: Bool { return LLVMIsAUnreachableInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ResumeInst` - public var isAResumeInst: Bool { + var isAResumeInst: Bool { return LLVMIsAResumeInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `CleanupReturnInst` - public var isACleanupReturnInst: Bool { + var isACleanupReturnInst: Bool { return LLVMIsACleanupReturnInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `CatchReturnInst` - public var isACatchReturnInst: Bool { + var isACatchReturnInst: Bool { return LLVMIsACatchReturnInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `FuncletPadInst` - public var isAFuncletPadInst: Bool { + var isAFuncletPadInst: Bool { return LLVMIsAFuncletPadInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `CatchPadInst` - public var isACatchPadInst: Bool { + var isACatchPadInst: Bool { return LLVMIsACatchPadInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `CleanupPadInst` - public var isACleanupPadInst: Bool { + var isACleanupPadInst: Bool { return LLVMIsACleanupPadInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `UnaryInstruction` - public var isAUnaryInstruction: Bool { + var isAUnaryInstruction: Bool { return LLVMIsAUnaryInstruction(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `AllocaInst` - public var isAAllocaInst: Bool { + var isAAllocaInst: Bool { return LLVMIsAAllocaInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `CastInst` - public var isACastInst: Bool { + var isACastInst: Bool { return LLVMIsACastInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `AddrSpaceCastInst` - public var isAAddrSpaceCastInst: Bool { + var isAAddrSpaceCastInst: Bool { return LLVMIsAAddrSpaceCastInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `BitCastInst` - public var isABitCastInst: Bool { + var isABitCastInst: Bool { return LLVMIsABitCastInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `FPExtInst` - public var isAFPExtInst: Bool { + var isAFPExtInst: Bool { return LLVMIsAFPExtInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `FPToSIInst` - public var isAFPToSIInst: Bool { + var isAFPToSIInst: Bool { return LLVMIsAFPToSIInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `FPToUIInst` - public var isAFPToUIInst: Bool { + var isAFPToUIInst: Bool { return LLVMIsAFPToUIInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `FPTruncInst` - public var isAFPTruncInst: Bool { + var isAFPTruncInst: Bool { return LLVMIsAFPTruncInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is an `IntToPtrInst` - public var isAIntToPtrInst: Bool { + var isAIntToPtrInst: Bool { return LLVMIsAIntToPtrInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `PtrToIntInst` - public var isAPtrToIntInst: Bool { + var isAPtrToIntInst: Bool { return LLVMIsAPtrToIntInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `SExtInst` - public var isASExtInst: Bool { + var isASExtInst: Bool { return LLVMIsASExtInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `SIToFPInst` - public var isASIToFPInst: Bool { + var isASIToFPInst: Bool { return LLVMIsASIToFPInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `TruncInst` - public var isATruncInst: Bool { + var isATruncInst: Bool { return LLVMIsATruncInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `UIToFPInst` - public var isAUIToFPInst: Bool { + var isAUIToFPInst: Bool { return LLVMIsAUIToFPInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ZExtInst` - public var isAZExtInst: Bool { + var isAZExtInst: Bool { return LLVMIsAZExtInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `ExtractValueInst` - public var isAExtractValueInst: Bool { + var isAExtractValueInst: Bool { return LLVMIsAExtractValueInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `LoadInst` - public var isALoadInst: Bool { + var isALoadInst: Bool { return LLVMIsALoadInst(asLLVM()) != nil } /// Whether or not the underlying LLVM value is a `VAArgInst` - public var isAVAArgInst: Bool { + var isAVAArgInst: Bool { return LLVMIsAVAArgInst(asLLVM()) != nil } } diff --git a/Sources/LLVM/IRValue.swift b/Sources/LLVM/IRValue.swift index 7a2bace4..9c30d5a5 100644 --- a/Sources/LLVM/IRValue.swift +++ b/Sources/LLVM/IRValue.swift @@ -11,27 +11,32 @@ public protocol IRValue { public extension IRValue { /// Retrieves the type of this value. - public var type: IRType { + var type: IRType { return convertType(LLVMTypeOf(asLLVM())) } /// Returns whether this value is a constant. - public var isConstant: Bool { + var isConstant: Bool { return LLVMIsConstant(asLLVM()) != 0 } + /// Returns whether this value is an instruction. + var isInstruction: Bool { + return LLVMIsAInstruction(asLLVM()) != nil + } + /// Returns whether this value has been initialized with the special `undef` /// value. /// /// The `undef` value can be used anywhere a constant is expected, and /// indicates that the user of the value may receive an unspecified /// bit-pattern. - public var isUndef: Bool { + var isUndef: Bool { return LLVMIsUndef(asLLVM()) != 0 } /// Gets and sets the name for this value. - public var name: String { + var name: String { get { let ptr = LLVMGetValueName(asLLVM())! return String(cString: ptr) @@ -41,31 +46,109 @@ public extension IRValue { } } - /// Perform a GEP (Get Element Pointer) with this value as the base. - /// - /// - parameter indices: A list of indices that indicate which of the elements - /// of the aggregate object are indexed. - /// - /// - returns: A value representing the address of a subelement of the given - /// aggregate data structure value. - public func constGEP(indices: [IRValue]) -> IRValue { - var idxs = indices.map { $0.asLLVM() as Optional } - return idxs.withUnsafeMutableBufferPointer { buf in - return LLVMConstGEP(asLLVM(), buf.baseAddress, UInt32(buf.count)) - } - } - /// Replaces all uses of this value with the specified value. /// /// - parameter value: The new value to swap in. - public func replaceAllUses(with value: IRValue) { + func replaceAllUses(with value: IRValue) { LLVMReplaceAllUsesWith(asLLVM(), value.asLLVM()) } /// Dumps a representation of this value to stderr. - public func dump() { + func dump() { LLVMDumpValue(asLLVM()) } + + /// The kind of this value. + var kind: IRValueKind { + return IRValueKind(llvm: LLVMGetValueKind(asLLVM())) + } +} + +/// Enumerates the kinds of values present in LLVM IR. +public enum IRValueKind { + /// The value is an argument. + case argument + /// The value is a basic block. + case basicBlock + /// The value is a memory use. + case memoryUse + /// The value is a memory definition. + case memoryDef + /// The value is a memory phi node. + case memoryPhi + /// The value is a function. + case function + /// The value is a global alias. + case globalAlias + /// The value is an ifunc. + case globalIFunc + /// The value is a variable. + case globalVariable + /// The value is a block address. + case blockAddress + /// The value is a constant expression. + case constantExpression + /// The value is a constant array. + case constantArray + /// The value is a constant struct. + case constantStruct + /// The value is a constant vector. + case constantVector + /// The value is undef. + case undef + /// The value is a constant aggregate zero. + case constantAggregateZero + /// The value is a constant data array. + case constantDataArray + /// The value is a constant data vector. + case constantDataVector + /// The value is a constant int value. + case constantInt + /// The value is a constant floating pointer value. + case constantFloat + /// The value is a constant pointer to null. + /// + /// Note that this pointer is a zero bit-value pointer. Its semantics are dependent upon the address space. + case constantPointerNull + /// The value is a constant none-token value. + case constantTokenNone + /// The value is a metadata-as-value node. + case metadataAsValue + /// The value is inline assembly. + case inlineASM + /// The value is an instruction. + case instruction + + init(llvm: LLVMValueKind) { + switch llvm { + case LLVMArgumentValueKind: self = .argument + case LLVMBasicBlockValueKind: self = .basicBlock + case LLVMMemoryUseValueKind: self = .memoryUse + case LLVMMemoryDefValueKind: self = .memoryDef + case LLVMMemoryPhiValueKind: self = .memoryPhi + case LLVMFunctionValueKind: self = .function + case LLVMGlobalAliasValueKind: self = .globalAlias + case LLVMGlobalIFuncValueKind: self = .globalIFunc + case LLVMGlobalVariableValueKind: self = .globalVariable + case LLVMBlockAddressValueKind: self = .blockAddress + case LLVMConstantExprValueKind: self = .constantExpression + case LLVMConstantArrayValueKind: self = .constantArray + case LLVMConstantStructValueKind: self = .constantStruct + case LLVMConstantVectorValueKind: self = .constantVector + case LLVMUndefValueValueKind: self = .undef + case LLVMConstantAggregateZeroValueKind: self = .constantAggregateZero + case LLVMConstantDataArrayValueKind: self = .constantDataArray + case LLVMConstantDataVectorValueKind: self = .constantDataVector + case LLVMConstantIntValueKind: self = .constantInt + case LLVMConstantFPValueKind: self = .constantFloat + case LLVMConstantPointerNullValueKind: self = .constantPointerNull + case LLVMConstantTokenNoneValueKind: self = .constantTokenNone + case LLVMMetadataAsValueValueKind: self = .metadataAsValue + case LLVMInlineAsmValueKind: self = .inlineASM + case LLVMInstructionValueKind: self = .instruction + default: fatalError("unknown IRValue kind \(llvm)") + } + } } extension LLVMValueRef: IRValue { @@ -75,6 +158,12 @@ extension LLVMValueRef: IRValue { } } +// N.B. This conformance is strictly not correct, but LLVM-C chooses to muddy +// the difference between LLVMValueRef and a number of what should be refined +// types. What matters is that we verify any returned `IRInstruction` values +// are actually instructions. +extension LLVMValueRef: IRInstruction {} + extension Int: IRValue { /// Retrieves the underlying LLVM value object. public func asLLVM() -> LLVMValueRef { diff --git a/Sources/LLVM/Instruction.swift b/Sources/LLVM/Instruction.swift index c8573709..0f61f1be 100644 --- a/Sources/LLVM/Instruction.swift +++ b/Sources/LLVM/Instruction.swift @@ -1,48 +1,46 @@ #if SWIFT_PACKAGE import cllvm +import llvmshims #endif -/// An `Instruction` represents an instruction residing in a basic block. -public struct Instruction: IRValue { - internal let llvm: LLVMValueRef - - /// Creates an `Intruction` from an `LLVMValueRef` object. - public init(llvm: LLVMValueRef) { - self.llvm = llvm - } - - /// Retrieves the underlying LLVM value object. - public func asLLVM() -> LLVMValueRef { - return llvm - } +/// An `IRInstruction` is a value that directly represents an instruction and +/// in particular the result of the execution of that instruction. +public protocol IRInstruction: IRValue { } +extension IRInstruction { /// Retrieves the opcode associated with this `Instruction`. public var opCode: OpCode { - return OpCode(rawValue: LLVMGetInstructionOpcode(llvm)) + return OpCode(rawValue: LLVMGetInstructionOpcode(self.asLLVM())) + } + + /// Retrieves the current debug location of this instruction. + public var debugLocation: DebugLocation? { + get { return LLVMInstructionGetDebugLoc(self.asLLVM()).map(DebugLocation.init(llvm:)) } + set { LLVMInstructionSetDebugLoc(self.asLLVM(), newValue?.asMetadata()) } } /// Obtain the instruction that occurs before this one, if it exists. public func previous() -> Instruction? { - guard let val = LLVMGetPreviousInstruction(llvm) else { return nil } + guard let val = LLVMGetPreviousInstruction(self.asLLVM()) else { return nil } return Instruction(llvm: val) } /// Obtain the instruction that occurs after this one, if it exists. public func next() -> Instruction? { - guard let val = LLVMGetNextInstruction(llvm) else { return nil } + guard let val = LLVMGetNextInstruction(self.asLLVM()) else { return nil } return Instruction(llvm: val) } /// Retrieves the parent basic block that contains this instruction, if it /// exists. public var parentBlock: BasicBlock? { - guard let parent = LLVMGetInstructionParent(self.llvm) else { return nil } + guard let parent = LLVMGetInstructionParent(self.asLLVM()) else { return nil } return BasicBlock(llvm: parent) } /// Retrieves the first use of this instruction. public var firstUse: Use? { - guard let use = LLVMGetFirstUse(llvm) else { return nil } + guard let use = LLVMGetFirstUse(self.asLLVM()) else { return nil } return Use(llvm: use) } @@ -57,11 +55,44 @@ public struct Instruction: IRValue { } } } + + /// Removes this instruction from a basic block but keeps it alive. + /// + /// - note: To ensure correct removal of the instruction, you must invalidate + /// any remaining references to its result values. + public func removeFromParent() { + LLVMInstructionRemoveFromParent(self.asLLVM()) + } +} + + +/// An `Instruction` represents an instruction residing in a basic block. +public struct Instruction: IRInstruction { + internal let llvm: LLVMValueRef + + /// Creates an `Intruction` from an `LLVMValueRef` object. + public init(llvm: LLVMValueRef) { + self.llvm = llvm + } + + /// Retrieves the underlying LLVM value object. + public func asLLVM() -> LLVMValueRef { + return llvm + } + + /// Create a copy of 'this' instruction that is identical in all ways except + /// the following: + /// + /// - The instruction has no parent + /// - The instruction has no name + public func clone() -> Instruction { + return Instruction(llvm: LLVMInstructionClone(self.llvm)) + } } /// A `TerminatorInstruction` represents an instruction that terminates a /// basic block. -public struct TerminatorInstruction { +public struct TerminatorInstruction: IRInstruction { internal let llvm: LLVMValueRef /// Creates a `TerminatorInstruction` from an `LLVMValueRef` object. @@ -84,4 +115,8 @@ public struct TerminatorInstruction { public func setSuccessor(at idx: Int, to bb: BasicBlock) { LLVMSetSuccessor(llvm, UInt32(idx), bb.asLLVM()) } + + public func asLLVM() -> LLVMValueRef { + return self.llvm + } } diff --git a/Sources/LLVM/IntType.swift b/Sources/LLVM/IntType.swift index 5ef45282..85170d09 100644 --- a/Sources/LLVM/IntType.swift +++ b/Sources/LLVM/IntType.swift @@ -41,7 +41,7 @@ public struct IntType: IRType { /// zero-bits. /// /// - returns: A value consisting of all zero-bits of this type's bit width. - public func zero() -> IRValue { + public func zero() -> IRConstant { return null() } @@ -91,8 +91,8 @@ public struct IntType: IRType { /// one-bits. /// /// - returns: A value consisting of all one-bits of this type's bit width. - public func allOnes() -> IRValue { - return LLVMConstAllOnes(asLLVM()) + public func allOnes() -> IRConstant { + return Constant(llvm: LLVMConstAllOnes(asLLVM())) } /// Retrieves the underlying LLVM type object. @@ -100,3 +100,9 @@ public struct IntType: IRType { return LLVMIntTypeInContext(context.llvm, UInt32(width)) } } + +extension IntType: Equatable { + public static func == (lhs: IntType, rhs: IntType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() + } +} diff --git a/Sources/LLVM/Intrinsic.swift b/Sources/LLVM/Intrinsic.swift new file mode 100644 index 00000000..11383bd8 --- /dev/null +++ b/Sources/LLVM/Intrinsic.swift @@ -0,0 +1,216 @@ +#if SWIFT_PACKAGE +import cllvm +import llvmshims +#endif +import Foundation + +/// An `Intrinsic` represents an intrinsic known to LLVM. +/// +/// Intrinsic functions have well known names and semantics and are required to +/// follow certain restrictions. Overall, these intrinsics represent an +/// extension mechanism for the LLVM language that does not require changing all +/// of the transformations in LLVM when adding to the language (or the bitcode +/// reader/writer, the parser, etc…). +/// +/// Intrinsic function names must all start with an `llvm.` prefix. This prefix +/// is reserved in LLVM for intrinsic names; thus, function names may not begin +/// with this prefix. Intrinsic functions must always be external functions: you +/// cannot define the body of intrinsic functions. Intrinsic functions may only +/// be used in call or invoke instructions: it is illegal to take the address of +/// an intrinsic function. +/// +/// Some intrinsic functions can be overloaded, i.e., the intrinsic represents a +/// family of functions that perform the same operation but on different data +/// types. Because LLVM can represent over 8 million different integer types, +/// overloading is used commonly to allow an intrinsic function to operate on +/// any integer type. One or more of the argument types or the result type can +/// be overloaded to accept any integer type. Argument types may also be defined +/// as exactly matching a previous argument’s type or the result type. This +/// allows an intrinsic function which accepts multiple arguments, but needs all +/// of them to be of the same type, to only be overloaded with respect to a +/// single argument or the result. +/// +/// Overloaded intrinsics will have the names of its overloaded argument types +/// encoded into its function name, each preceded by a period. Only those types +/// which are overloaded result in a name suffix. Arguments whose type is +/// matched against another type do not. For example, the llvm.ctpop function +/// can take an integer of any width and returns an integer of exactly the same +/// integer width. This leads to a family of functions such as +/// `i8 @llvm.ctpop.i8(i8 %val)` and `i29 @llvm.ctpop.i29(i29 %val)`. Only one +/// type, the return type, is overloaded, and only one type suffix is required. +/// Because the argument’s type is matched against the return type, it does not +/// require its own name suffix. +/// +/// Dynamic Member Lookup For Intrinsics +/// ==================================== +/// +/// This library provides a dynamic member lookup facility for retrieving +/// intrinsic selectors. For any LLVM intrinsic selector of the form +/// `llvm.foo.bar.baz`, the name of the corresponding dynamic member is that +/// name with any dots replaced by underscores. +/// +/// For example: +/// +/// llvm.foo.bar.baz -> Intrinsic.ID.llvm_foo_bar_baz +/// llvm.stacksave -> Intrinsic.ID.llvm_stacksave +/// llvm.x86.xsave64 -> Intrinsic.ID.llvm_x86_xsave64 +/// +/// Any existing underscores do not need to be replaced, e.g. +/// `llvm.va_copy` becomes `Intrinsic.ID.llvm_va_copy`. +/// +/// For overloaded intrinsics, the non-overloaded prefix excluding the explicit +/// type parameters is used and normalized according to the convention above. +/// +/// For example: +/// +/// llvm.sinf64 -> Intrinsic.ID.llvm_sin +/// llvm.memcpy.p0i8.p0i8.i32 -> Intrinsic.ID.llvm_memcpy +/// llvm.bswap.v4i32 -> Intrinsic.ID.llvm_bswap +public class Intrinsic: Function { + /// A wrapper type for an intrinsic selector. + public struct Selector { + let index: UInt32 + fileprivate init(_ index: UInt32) { self.index = index } + } + + /// This type provides a dynamic member lookup facility for LLVM intrinsics. + /// + /// It is not possible to create a `DynamicIntrinsicResolver` in user code. + /// One is provided by `Intrinsic.ID`. + @dynamicMemberLookup public struct DynamicIntrinsicResolver { + private let exceptionalSet: Set + + fileprivate init() { + // LLVM naming conventions for intrinsics is really not consistent at all + // (see llvm.ssa_copy). We need to gather a table of all the intrinsics + // that have underscores in their names so we don't naively replace them + // with dots later. + // + // Luckily, no intrinsics that use underscores in their name also use + // dots. If this changes in the future, we need to be smarter here. + var table = Set() + table.reserveCapacity(16) + for idx in 1.. Intrinsic.ID.llvm_foo_bar_baz + /// llvm.stacksave -> Intrinsic.ID.llvm_stacksave + /// llvm.x86.xsave64 -> Intrinsic.ID.llvm_x86_xsave64 + /// + /// Any existing underscores do not need to be replaced, e.g. + /// `llvm.va_copy` becomes `Intrinsic.ID.llvm_va_copy`. + /// + /// For overloaded intrinsics, the non-overloaded prefix excluding the + /// explicit type parameters is used and normalized according to the + /// convention above. + /// + /// For example: + /// + /// llvm.sinf64 -> Intrinsic.ID.llvm_sin + /// llvm.memcpy.p0i8.p0i8.i32 -> Intrinsic.ID.llvm_memcpy + /// llvm.bswap.v4i32 -> Intrinsic.ID.llvm_bswap + /// + /// - Parameter selector: The LLVMSwift form of an intrinsic selector. + public subscript(dynamicMember selector: String) -> Selector { + precondition(selector.starts(with: "llvm_")) + + let prefix = "llvm." + let suffix = selector.dropFirst("llvm_".count) + let finalSelector: String + if self.exceptionalSet.contains(prefix + suffix) { + // If the exceptions set contains an entry for this selector, then it + // has an underscore and no dots so we can just concatenate prefix and + // suffix. + finalSelector = prefix + suffix + } else { + // Else, naively replace all the underscores with dots. + finalSelector = selector.replacingOccurrences(of: "_", with: ".") + } + + let index = LLVMLookupIntrinsicID(finalSelector, finalSelector.count) + assert(index > 0, "Member does not correspond to an LLVM intrinsic") + return Selector(index) + } + } + + /// The default dynamic intrinsic resolver. + public static let ID = DynamicIntrinsicResolver() + + /// Retrieves the name of this intrinsic if it is not overloaded. + public var name: String { + precondition(!self.isOverloaded, + "Cannot retrieve the full name of an overloaded intrinsic") + var count = 0 + guard let ptr = LLVMIntrinsicGetName(self.identifier, &count) else { + return "" + } + return String(cString: ptr) + } + + /// Retrieves the name of this intrinsic if it is overloaded, resolving it + /// with the given parameter types. + public func overloadedName(for parameterTypes: [IRType]) -> String { + precondition(self.isOverloaded, + "Cannot retrieve the overloaded name of a non-overloaded intrinsic") + var argIRTypes = parameterTypes.map { $0.asLLVM() as Optional } + return argIRTypes.withUnsafeMutableBufferPointer { buf -> String in + var count = 0 + guard let ptr = LLVMIntrinsicCopyOverloadedName(self.identifier, buf.baseAddress, parameterTypes.count, &count) else { + return "" + } + defer { free(UnsafeMutableRawPointer(mutating: ptr)) } + return String(cString: ptr) + } + } + + /// Retrieves the type of this intrinsic if it is not overloaded. + public var type: IRType { + precondition(!self.isOverloaded, + "Cannot retrieve type of overloaded intrinsic") + return convertType(LLVMTypeOf(asLLVM())) + } + + /// Resolves the type of an overloaded intrinsic using the given parameter + /// types. + /// + /// - Parameters: + /// - context: The context in which to create the type. + /// - parameterTypes: The type of the parameters to the intrinsic. + /// - Returns: The type of the intrinsic function with its overloaded + /// parameter types resolved. + public func overloadedType(in context: Context = .global, with parameterTypes: [IRType]) -> IRType { + var argIRTypes = parameterTypes.map { $0.asLLVM() as Optional } + return argIRTypes.withUnsafeMutableBufferPointer { buf -> IRType in + guard let ty = LLVMIntrinsicGetType(context.llvm, self.identifier, buf.baseAddress, parameterTypes.count) else { + fatalError("Could not retrieve type of intrinsic") + } + return convertType(ty) + } + } + + /// Retrieves if this intrinsic is overloaded. + public var isOverloaded: Bool { + return LLVMIntrinsicIsOverloaded(self.identifier) != 0 + } + + /// Retrieves the ID number of this intrinsic function. + public var identifier: UInt32 { + return LLVMGetIntrinsicID(self.llvm) + } +} diff --git a/Sources/LLVM/JIT.swift b/Sources/LLVM/JIT.swift index 497bdde2..2a89c4b0 100644 --- a/Sources/LLVM/JIT.swift +++ b/Sources/LLVM/JIT.swift @@ -5,21 +5,16 @@ import cllvm /// JITError represents the different kinds of errors the JIT compiler can /// throw. public enum JITError: Error, CustomStringConvertible { - /// The JIT was unable to be initialized. A message is provided explaining - /// the failure. - case couldNotInitialize(String) - - /// The JIT was unable to remove the provided module. A message is provided - /// explaining the failure - case couldNotRemoveModule(Module, String) + /// A generic error thrown by the JIT during exceptional circumstances. + /// + /// In general, it is not safe to catch and continue after this exception has + /// been thrown. + case generic(String) - /// A human-readable description of the error. public var description: String { switch self { - case .couldNotRemoveModule(let module, let message): - return "could not remove module '\(module.name)': \(message)" - case .couldNotInitialize(let message): - return "could not initialize JIT: \(message)" + case let .generic(desc): + return desc } } } @@ -28,133 +23,293 @@ public enum JITError: Error, CustomStringConvertible { /// that has been generated in a `Module`. It can execute arbitrary functions /// and return the value the function generated, allowing you to write /// interactive programs that will run as soon as they are compiled. +/// +/// The JIT is fundamentally lazy, and allows control over when and how symbols +/// are resolved. public final class JIT { - /// The underlying LLVMExecutionEngineRef backing this JIT. - internal let llvm: LLVMExecutionEngineRef - - /// Creates a Just In Time compiler that will compile the code in the - /// provided `Module` to the architecture of the provided `TargetMachine`, - /// and execute it. - /// - /// - parameters: - /// - module: The module containing code you wish to execute - /// - machine: The target machine which you're compiling for - /// - throws: JITError - public init(module: Module, machine: TargetMachine) throws { - var jit: LLVMExecutionEngineRef? - var error: UnsafeMutablePointer? - if LLVMCreateExecutionEngineForModule(&jit, module.llvm, &error) != 0 { - let str = String(cString: error!) - throw JITError.couldNotInitialize(str) + /// A type that represents an address, either symbolically within the JIT or + /// physically in the execution environment. + public struct TargetAddress: Comparable { + fileprivate var llvm: LLVMOrcTargetAddress + + /// Creates a target address value of `0`. + public init() { + self.llvm = 0 } - guard let _jit = jit else { - throw JITError.couldNotInitialize("JIT was NULL") + + /// Creates a target address from a raw address value. + public init(raw: LLVMOrcTargetAddress) { + self.llvm = raw } - self.llvm = _jit - LLVMRunStaticConstructors(self.llvm) - } - - /// Runs the specified function with the provided arguments by compiling - /// it to machine code for the target architecture used to initialize this - /// JIT. - /// - /// - parameters: - /// - function: The function you wish to execute - /// - args: The arguments you wish to pass to the function - /// - returns: The LLVM value that the function returned - public func runFunction(_ function: Function, args: [IRValue]) -> IRValue { - var irArgs = args.map { $0.asLLVM() as Optional } - return irArgs.withUnsafeMutableBufferPointer { buf in - return LLVMRunFunction(llvm, function.asLLVM(), - UInt32(buf.count), buf.baseAddress) + + public static func == (lhs: TargetAddress, rhs: TargetAddress) -> Bool { + return lhs.llvm == rhs.llvm } - } - /// Retrieves a pointer to the function compiled by this JIT. - /// - parameter name: The name of the function you wish to look up. - /// - returns: A pointer to the result of compiling the specified function. - /// - note: You will have to `unsafeBitCast` this pointer to - /// the appropriate `@convention(c)` function type to be - /// able to run it from Swift. - /// - /// ``` - /// typealias FnPtr = @convention(c) () -> Double - /// let fnAddr = jit.addressOfFunction(name: "test") - /// let fn = unsafeBitCast(fnAddr, to: FnPtr.self) - /// ``` - public func addressOfFunction(name: String) -> OpaquePointer? { - let addr = LLVMGetFunctionAddress(llvm, name) - guard addr != 0 else { return nil } - return OpaquePointer(bitPattern: UInt(addr)) - } - - /// Adds the provided module, and all top-level declarations into this JIT. - /// - parameter module: The module you wish to add. - public func addModule(_ module: Module) { - LLVMAddModule(llvm, module.llvm) - } - - /// Removes the provided module, and all top-level declarations, from this - /// JIT. - public func removeModule(_ module: Module) throws { - var outMod: LLVMModuleRef? = module.llvm - var outError: UnsafeMutablePointer? - LLVMRemoveModule(llvm, module.llvm, &outMod, &outError) - if let err = outError { - defer { LLVMDisposeMessage(err) } - throw JITError.couldNotRemoveModule(module, String(cString: err)) + public static func < (lhs: TargetAddress, rhs: TargetAddress) -> Bool { + return lhs.llvm < rhs.llvm } } - /// Runs the specified function as if it were the `main` function in an - /// executable. It takes an array of argument strings and passes them - /// into the function as `argc` and `argv`. - /// - /// - parameters: - /// - function: The `main` function you wish to execute - /// - args: The string arguments you wish to pass to the function - /// - returns: The numerical exit code returned by the function - public func runFunctionAsMain(_ function: Function, args: [String]) -> Int { - // FIXME: Also add in envp. - return withCArrayOfCStrings(args) { buf in - return Int(LLVMRunFunctionAsMain(llvm, function.asLLVM(), - UInt32(buf.count), - buf.baseAddress, nil)) - } + /// Represents a handle to a module owned by the JIT stack. + public struct ModuleHandle { + fileprivate var llvm: LLVMOrcModuleHandle + } + + /// The underlying LLVMExecutionEngineRef backing this JIT. + internal let llvm: LLVMOrcJITStackRef + private let ownsContext: Bool + + internal init(llvm: LLVMOrcJITStackRef, ownsContext: Bool) { + self.llvm = llvm + self.ownsContext = ownsContext + } + + /// Create and initialize a `JIT` with this target machine's representation. + public convenience init(machine: TargetMachine) { + // The JIT stack takes ownership of the target machine. + machine.ownsContext = false + self.init(llvm: LLVMOrcCreateInstance(machine.llvm), ownsContext: true) } + /// Deinitialize this value and dispose of its resources. deinit { - LLVMRunStaticDestructors(self.llvm) + guard self.ownsContext else { + return + } + _ = LLVMOrcDisposeInstance(self.llvm) } -} -/// Runs the provided block with the equivalent C strings copied from the -/// passed-in array. The C strings will only be alive for the duration -/// of the block, and they will be freed when the block exits. -/// -/// - parameters: -/// - strings: The strings you intend to convert to C strings -/// - block: A block that uses the C strings -/// - returns: The result of the passed-in block. -/// - throws: Will only throw if the passed-in block throws. -internal func withCArrayOfCStrings(_ strings: [String], _ block: - (UnsafeBufferPointer?>) throws -> T) rethrows -> T { - var cStrings = [UnsafeMutablePointer?]() - for string in strings { - string.withCString { - cStrings.append(strdup($0)) + // MARK: Symbols + + /// Mangles the given symbol name according to the data layout of the JIT's + /// target machine. + /// + /// - parameter symbol: The symbol name to mangle. + /// - returns: A mangled representation of the given symbol name. + public func mangle(symbol: String) -> String { + var mangledResult: UnsafeMutablePointer? = nil + LLVMOrcGetMangledSymbol(self.llvm, &mangledResult, symbol) + guard let result = mangledResult else { + fatalError("Mangled name should never be nil!") } + defer { LLVMOrcDisposeMangledSymbol(mangledResult) } + return String(cString: result) + } + + /// Computes the address of the given symbol, optionally restricting the + /// search for its address to a particular module. If this symbol does not + /// exist, an address of `0` is returned. + /// + /// - parameter symbol: The symbol name to search for. + /// - parameter module: An optional value describing the module in which to + /// restrict the search, if any. + /// - returns: The address of the symbol, or 0 if it does not exist. + public func address(of symbol: String, in module: ModuleHandle? = nil) throws -> TargetAddress { + var retAddr: LLVMOrcTargetAddress = 0 + if let targetModule = module { + try checkForJITError(LLVMOrcGetSymbolAddressIn(self.llvm, &retAddr, targetModule.llvm, symbol)) + } else { + try checkForJITError(LLVMOrcGetSymbolAddress(self.llvm, &retAddr, symbol)) + } + return TargetAddress(raw: retAddr) + } + + // MARK: Lazy Compilation + + /// Registers a lazy compile callback that can be used to get the target + /// address of a trampoline function. When that trampoline address is + /// called, the given compilation callback is fired. + /// + /// Normally, the trampoline function is a known stub that has been previously + /// registered with the JIT. The callback then computes the address of a + /// known entry point and sets the address of the stub to it. See + /// `JIT.createIndirectStub` to create a stub function and + /// `JIT.setIndirectStubPointer` to set the address of a stub. + /// + /// - parameter callback: A callback that returns the actual address of the + /// trampoline function. + /// - returns: The target address representing a stub. Calling this stub + /// forces the given compilation callback to fire. + public func registerLazyCompile(_ callback: @escaping (JIT) -> TargetAddress) throws -> TargetAddress { + var addr: LLVMOrcTargetAddress = 0 + let callbackContext = ORCLazyCompileCallbackContext(callback) + let contextPtr = Unmanaged.passRetained(callbackContext).toOpaque() + try checkForJITError(LLVMOrcCreateLazyCompileCallback(self.llvm, &addr, lazyCompileBlockTrampoline, contextPtr)) + return TargetAddress(raw: addr) + } + + // MARK: Stubs + + /// Creates a new named indirect stub pointing to the given target address. + /// + /// An indirect stub may be resolved to a different address at any time by + /// invoking `JIT.setIndirectStubPointer`. + /// + /// - parameter name: The name of the indirect stub. + /// - parameter address: The address of the indirect stub. + public func createIndirectStub(named name: String, address: TargetAddress) throws { + try checkForJITError(LLVMOrcCreateIndirectStub(self.llvm, name, address.llvm)) + } + + /// Resets the address of an indirect stub. + /// + /// - warning: The indirect stub must be registered with a call to + /// `JIT.createIndirectStub`. Failure to do so will result in undefined + /// behavior. + /// + /// - parameter name: The name of an indirect stub. + /// - parameter address: The address to set the indirect stub to point to. + public func setIndirectStubPointer(named name: String, address: TargetAddress) throws { + try checkForJITError(LLVMOrcSetIndirectStubPointer(self.llvm, name, address.llvm)) + } + + // MARK: Adding Code to the JIT + + /// Adds the IR from a given module to the JIT, consuming it in the process. + /// + /// Despite the name of this function, the callback to compile the symbols in + /// the module is not necessarily called immediately. It is called at least + /// when a given symbol's address is requested, either by the JIT or by + /// the user e.g. `JIT.address(of:)`. + /// + /// The callback function is required to compute the address of the given + /// symbol. The symbols are passed in mangled form. Use + /// `JIT.mangle(symbol:)` to request the mangled name of a symbol. + /// + /// - warning: The JIT invalidates the underlying reference to the provided + /// module. Further references to the module are thus dangling pointers and + /// may be a source of subtle memory bugs. This will be addressed in a + /// future revision of LLVM. + /// + /// - parameter module: The module to compile. + /// - parameter callback: A function that is called by the JIT to compute the + /// address of symbols. + public func addEagerlyCompiledIR(_ module: Module, _ callback: @escaping (String) -> TargetAddress) throws -> ModuleHandle { + var handle: LLVMOrcModuleHandle = 0 + let callbackContext = ORCSymbolCallbackContext(callback) + let contextPtr = Unmanaged.passRetained(callbackContext).toOpaque() + // The JIT stack takes ownership of the given module. + module.ownsContext = false + try checkForJITError(LLVMOrcAddEagerlyCompiledIR(self.llvm, &handle, module.llvm, symbolBlockTrampoline, contextPtr)) + return ModuleHandle(llvm: handle) + } + + /// Adds the IR from a given module to the JIT, consuming it in the process. + /// + /// This function differs from `JIT.addEagerlyCompiledIR` in that the callback + /// to request the address of symbols is only executed when that symbol is + /// called, either in user code or by the JIT. + /// + /// The callback function is required to compute the address of the given + /// symbol. The symbols are passed in mangled form. Use + /// `JIT.mangle(symbol:)` to request the mangled name of a symbol. + /// + /// - warning: The JIT invalidates the underlying reference to the provided + /// module. Further references to the module are thus dangling pointers and + /// may be a source of subtle memory bugs. This will be addressed in a + /// future revision of LLVM. + /// + /// - parameter module: The module to compile. + /// - parameter callback: A function that is called by the JIT to compute the + /// address of symbols. + public func addLazilyCompiledIR(_ module: Module, _ callback: @escaping (String) -> TargetAddress) throws -> ModuleHandle { + var handle: LLVMOrcModuleHandle = 0 + let callbackContext = ORCSymbolCallbackContext(callback) + let contextPtr = Unmanaged.passRetained(callbackContext).toOpaque() + // The JIT stack takes ownership of the given module. + module.ownsContext = false + try checkForJITError(LLVMOrcAddLazilyCompiledIR(self.llvm, &handle, module.llvm, symbolBlockTrampoline, contextPtr)) + return ModuleHandle(llvm: handle) + } + + /// Adds the executable code from an object file to ths JIT, consuming it in + /// the process. + /// + /// The callback function is required to compute the address of the given + /// symbol. The symbols are passed in mangled form. Use + /// `JIT.mangle(symbol:)` to request the mangled name of a symbol. + /// + /// - warning: The JIT invalidates the underlying reference to the provided + /// memory buffer. Further references to the buffer are thus dangling + /// pointers and may be a source of subtle memory bugs. This will be + /// addressed in a future revision of LLVM. + /// + /// - parameter buffer: A buffer containing an object file. + /// - parameter callback: A function that is called by the JIT to compute the + /// address of symbols. + public func addObjectFile(_ buffer: MemoryBuffer, _ callback: @escaping (String) -> TargetAddress) throws -> ModuleHandle { + var handle: LLVMOrcModuleHandle = 0 + let callbackContext = ORCSymbolCallbackContext(callback) + let contextPtr = Unmanaged.passRetained(callbackContext).toOpaque() + // The JIT stack takes ownership of the given buffer. + buffer.ownsContext = false + try checkForJITError(LLVMOrcAddObjectFile(self.llvm, &handle, buffer.llvm, symbolBlockTrampoline, contextPtr)) + return ModuleHandle(llvm: handle) } - defer { - for cStr in cStrings { - free(cStr) + + /// Remove previously-added code from the JIT. + /// + /// - warning: Removing a module handle consumes the handle. Further use of + /// the handle will then result in undefined behavior. + /// + /// - parameter handle: A handle to previously-added module. + public func removeModule(_ handle: ModuleHandle) throws { + try checkForJITError(LLVMOrcRemoveModule(self.llvm, handle.llvm)) + } + + private func checkForJITError(_ orcError: LLVMErrorRef!) throws { + guard let err = orcError else { + return } + + switch LLVMGetErrorTypeId(err)! { + case LLVMGetStringErrorTypeId(): + guard let msg = LLVMGetErrorMessage(err) else { + fatalError("Couldn't get the error message?") + } + throw JITError.generic(String(cString: msg)) + default: + guard let msg = LLVMOrcGetErrorMsg(self.llvm) else { + fatalError("Couldn't get the error message?") + } + throw JITError.generic(String(cString: msg)) + } + } +} + +private let lazyCompileBlockTrampoline : LLVMOrcLazyCompileCallbackFn = { (callbackJIT, callbackCtx) in + guard let jit = callbackJIT, let ctx = callbackCtx else { + fatalError("Internal JIT callback and context must be non-nil") } - return try cStrings.withUnsafeBufferPointer { buf in - // We need to make this "immutable" but that doesn't change - // their size or contents. - let constPtr = unsafeBitCast(buf.baseAddress, - to: UnsafePointer?>.self) - return try block(UnsafeBufferPointer(start: constPtr, count: buf.count)) + + let tempJIT = JIT(llvm: jit, ownsContext: false) + let callback = Unmanaged.fromOpaque(ctx).takeUnretainedValue() + return callback.block(tempJIT).llvm +} + +private let symbolBlockTrampoline : LLVMOrcSymbolResolverFn = { (callbackName, callbackCtx) in + guard let cname = callbackName, let ctx = callbackCtx else { + fatalError("Internal JIT name and context must be non-nil") + } + + let name = String(cString: cname) + let callback = Unmanaged.fromOpaque(ctx).takeUnretainedValue() + return callback.block(name).llvm +} + +private class ORCLazyCompileCallbackContext { + fileprivate let block: (JIT) -> JIT.TargetAddress + + fileprivate init(_ block: @escaping (JIT) -> JIT.TargetAddress) { + self.block = block + } +} + +private class ORCSymbolCallbackContext { + fileprivate let block: (String) -> JIT.TargetAddress + + fileprivate init(_ block: @escaping (String) -> JIT.TargetAddress) { + self.block = block } } diff --git a/Sources/LLVM/LabelType.swift b/Sources/LLVM/LabelType.swift index 974ecc4d..acb36ae8 100644 --- a/Sources/LLVM/LabelType.swift +++ b/Sources/LLVM/LabelType.swift @@ -21,3 +21,9 @@ public struct LabelType: IRType { return LLVMLabelTypeInContext(context.llvm) } } + +extension LabelType: Equatable { + public static func == (lhs: LabelType, rhs: LabelType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() + } +} diff --git a/Sources/LLVM/Linkage.swift b/Sources/LLVM/Linkage.swift index 336ff724..6c2f13aa 100644 --- a/Sources/LLVM/Linkage.swift +++ b/Sources/LLVM/Linkage.swift @@ -216,3 +216,50 @@ public enum StorageClass { return StorageClass.storageMapping[self]! } } + +/// Enumerates values representing whether or not this global value's address +/// is significant in this module or the program at large. A global value's +/// address is considered significant if it is referenced by any module in the +/// final program. +/// +/// This attribute is intended to be used only by the code generator and LTO to +/// allow the linker to decide whether the global needs to be in the symbol +/// table. Constant global values with unnamed addresses and identical +/// initializers may be merged by LLVM. Note that a global value with an +/// unnamed address may be merged with a global value with a significant address +/// resulting in a global value with a significant address. +public enum UnnamedAddressKind { + /// Indicates that the address of this global value is significant + /// in this module. + case none + + /// Indicates that the address of this global value is not significant to the + /// current module but it may or may not be significant to another module; + /// only the content of the value is known to be significant within the + /// current module. + case local + + /// Indicates that the address of this global value is not significant to the + /// current module or any other module; only the content of the value + /// is significant globally. + case global + + private static let unnamedAddressMapping: [UnnamedAddressKind: LLVMUnnamedAddr] = [ + .none: LLVMNoUnnamedAddr, + .local: LLVMLocalUnnamedAddr, + .global: LLVMGlobalUnnamedAddr, + ] + + internal init(llvm: LLVMUnnamedAddr) { + switch llvm { + case LLVMNoUnnamedAddr: self = .none + case LLVMLocalUnnamedAddr: self = .local + case LLVMGlobalUnnamedAddr: self = .global + default: fatalError("unknown unnamed address kind \(llvm)") + } + } + + internal var llvm: LLVMUnnamedAddr { + return UnnamedAddressKind.unnamedAddressMapping[self]! + } +} diff --git a/Sources/LLVM/MDBuilder.swift b/Sources/LLVM/MDBuilder.swift new file mode 100644 index 00000000..9ed1d915 --- /dev/null +++ b/Sources/LLVM/MDBuilder.swift @@ -0,0 +1,483 @@ +#if SWIFT_PACKAGE +import cllvm +import llvmshims +#endif + +/// An `MDBuilder` object provides a convenient way to build common metadata +/// nodes. +public final class MDBuilder { + /// The context used to intialize this metadata builder. + public let context: Context + + /// Creates a metadata builder with the given context. + /// + /// - Parameters: + /// - context: The context in which to create metadata. + public init(in context: Context = .global) { + self.context = context + } +} + +// MARK: Floating Point Accuracy Metadata + +extension MDBuilder { + /// Builds metadata describing the accuracy of a floating-point computation + /// using the given accuracy value. + /// + /// - Parameters: + /// - accuracy: The accuracy value. + /// - Returns: A metadata node describing the accuracy of a floating-point + /// computation. + public func buildFloatingPointMathTag(_ accuracy: Float) -> MDNode? { + guard accuracy > 0.0 else { + return nil + } + let op = MDNode(constant: FloatType(kind: .float, in: self.context).constant(Double(accuracy))) + return MDNode(in: self.context, operands: [ op ]) + } +} + +// MARK: Branch Prediction Metadata + +extension MDBuilder { + /// Builds branch weight metadata for a set of branch targets of a `branch`, + /// `select,` `switch`, or `call` instruction. + /// + /// - Parameters: + /// - weights: The weights of the branches. + /// - Returns: A metadata node containing the given branch-weight information. + public func buildBranchWeights(_ weights: [Int]) -> MDNode { + precondition(weights.count >= 1, "Branch weights must have at least one value") + var ops = [IRMetadata]() + ops.reserveCapacity(weights.count + 1) + ops.append(MDString("branch_weights")) + let int32Ty = IntType(width: 32, in: self.context) + for weight in weights { + ops.append(MDNode(constant: int32Ty.constant(weight))) + } + return MDNode(in: self.context, operands: ops) + } + + /// Builds branch metadata that expresses that the flow of control is + /// unpredictable in a given `branch` or `switch` instruction. + /// + /// - Returns: A metadata node representing unpredictable branch metadata. + public func buildUnpredictable() -> MDNode { + return MDNode(in: self.context, operands: []) + } +} + +// MARK: Section Prefix Metadata + +extension MDBuilder { + /// Builds section prefix metadata. + /// + /// LLVM allows an explicit section to be specified for functions. If the + /// target supports it, it will emit functions to the section specified. + /// Additionally, the function can be placed in a COMDAT. + /// + /// - Parameters: + /// - section: The section into which functions annotated with this + /// metadata should be emitted. + /// - Returns: A metadata node representing the section prefix metadata. + public func buildFunctionSectionPrefix(_ section: String) -> MDNode { + return MDNode(in: self.context, operands: [ + MDString("function_section_prefix"), + MDString(section), + ]) + } +} + +// MARK: Range Metadata + +extension MDBuilder { + /// Builds range metadata. + /// + /// Range metadata may be attached only to load, call and invoke of integer + /// types. It expresses the possible ranges the loaded value or the value + /// returned by the called function at this call site is in. If the loaded + /// or returned value is not in the specified range, the behavior is + /// undefined. + /// + /// - Parameters: + /// - lo: The lower bound on the range. + /// - hi: The upper bound on the range. + /// - Returns: A metadata node representing the newly created range metadata. + public func buildRange(_ lo: APInt, _ hi: APInt) -> MDNode? { + precondition(lo.bitWidth == hi.bitWidth, "Bitwidth of range limits must match!") + guard lo != hi else { + return nil + } + + return MDNode(in: self.context, operands: [ + MDNode(llvm: LLVMValueAsMetadata(lo.asLLVM())), + MDNode(llvm: LLVMValueAsMetadata(hi.asLLVM())), + ]) + } +} + +// MARK: Callee Metadata + +extension MDBuilder { + /// Build callees metadata. + /// + /// Callees metadata may be attached to indirect call sites. If callees + /// metadata is attached to a call site, and any callee is not among the + /// set of functions provided by the metadata, the behavior is undefined. + /// + /// - Parameters: + /// - callees: An array of callee function values. + /// - Returns: A metadata node representing the newly created callees metadata. + public func buildCallees(_ callees: [Function]) -> MDNode { + var ops = [IRMetadata]() + ops.reserveCapacity(callees.count) + for callee in callees { + ops.append(MDNode(constant: callee)) + } + return MDNode(in: self.context, operands: ops) + } +} + +// MARK: Callback Metadata + +extension MDBuilder { + /// Build Callback metadata. + /// + /// Callback metadata may be attached to a function declaration, or + /// definition. The metadata describes how the arguments of a call to a + /// function are in turn passed to the callback function specified by the + /// metadata. Thus, the callback metadata provides a partial description of + /// a call site inside the function with regards to the arguments of a call + /// to the function. The only semantic restriction on the function itself is + /// that it is not allowed to inspect or modify arguments referenced in the + /// callback metadata as pass-through to the callback function. + /// + /// - Parameters: + /// - callbackIndex: The argument index of the callback. + /// - argumentIndices: An array of argument indices in the caller that + /// are passed to the callback function. + /// - passVariadicArguments: If true, denotes that all variadic arguments + /// of the function are passed to the callback. + /// - Returns: A metadata node representing the newly created callees metadata. + public func buildCallbackEncoding( + _ callbackIndex: UInt, _ argumentIndices: [Int], + passVariadicArguments: Bool = false + ) -> MDNode { + var ops = [IRMetadata]() + let int64 = IntType(width: 64, in: self.context) + ops.append(MDNode(constant: int64.constant(callbackIndex))) + for argNo in argumentIndices { + ops.append(MDNode(constant: int64.constant(argNo))) + } + ops.append(MDNode(constant: IntType(width: 1, in: self.context).constant(passVariadicArguments ? 1 : 0))) + return MDNode(in: self.context, operands: ops) + } +} + +// MARK: Function Entry Count Metadata + +extension MDBuilder { + /// Build function entry count metadata. + /// + /// Function entry count metadata can be attached to function definitions to + /// record the number of times the function is called. Used with + /// block frequency information, it is also used to derive the basic block + /// profile count. + /// + /// - Parameters: + /// - count: The number of times a function is called. + /// - imports: The GUID of global values that should be imported along with + /// this function when running PGO. + /// - synthetic: Whether the entry count is synthetic. User-created + /// metadata should not be synthetic outside of PGO passes. + /// - Returns: A metadata node representing the newly created entry count metadata. + public func buildFunctionEntryCount( + _ count: UInt, imports: Set = [], synthetic: Bool = false + ) -> MDNode { + let int64 = IntType(width: 64, in: self.context) + var ops = [IRMetadata]() + if synthetic { + ops.append(MDString("synthetic_function_entry_count")) + } else { + ops.append(MDString("function_entry_count")) + } + ops.append(MDNode(constant: int64.constant(count))) + for id in imports.sorted() { + ops.append(MDNode(constant: int64.constant(id))) + } + return MDNode(in: self.context, operands: ops) + } +} + +// MARK: TBAA Metadata + +/// Represents a single field in a (C or C++) struct. +public struct TBAAStructField { + /// The offset of this struct field in bytes. + public let offset: Size + /// This size of this struct field in bytes. + public let size: Size + /// The type metadata node for this struct field. + public let type: MDNode + + /// Create a new TBAA struct field. + /// + /// - Parameters: + /// - The offsset of this field relative to its parent in bytes. + /// - The size of this field in bytes. + /// - TBAA type metadata for the field. + public init(offset: Size, size: Size, type: MDNode) { + self.offset = offset + self.size = size + self.type = type + } +} + +extension MDBuilder { + /// Build a metadata node for the root of a TBAA hierarchy with the given + /// name. + /// + /// The root node of a TBAA hierarchy describes a boundary for a source + /// language's type system. For the purposes of optimization, a TBAA analysis + /// pass must consider ancestors of two different root systems `mayalias`. + /// + /// - Parameters: + /// - name: The name of the TBAA root node. + /// - Returns: A metadata node representing a TBAA hierarchy root. + public func buildTBAARoot(_ name: String = "") -> MDNode { + guard !name.isEmpty else { + return self.buildAnonymousAARoot() + } + return MDNode(in: self.context, operands: [ MDString(name) ]) + } + + /// Build a metadata node suitable for an `alias.scope` metadata attachment. + /// + /// When evaluating an aliasing query, if for some domain, the set of scopes + /// with that domain in one instruction’s alias.scope list is a subset of (or + /// equal to) the set of scopes for that domain in another instruction’s + /// noalias list, then the two memory accesses are assumed not to alias. + /// + /// Because scopes in one domain don’t affect scopes in other domains, + /// separate domains can be used to compose multiple independent noalias + /// sets. This is used for example during inlining. As the noalias function + /// parameters are turned into noalias scope metadata, a new domain is used + /// every time the function is inlined. + /// + /// - Parameters: + /// - name: The name of the alias scope domain. + /// - domain: The domain of the alias scope, if any. + /// - Returns: A metadata node representing a TBAA alias scope. + public func buildAliasScopeDomain(_ name: String = "", _ domain: MDNode? = nil) -> MDNode { + if name.isEmpty { + if let domain = domain { + return self.buildAnonymousAARoot(name, domain) + } + return self.buildAnonymousAARoot(name) + } else { + if let domain = domain { + return MDNode(in: self.context, operands: [ MDString(name), domain ]) + } + return MDNode(in: self.context, operands: [ MDString(name) ]) + } + } + + /// Builds a metadata node suitable for a `tbaa.struct` metadata attachment. + /// + /// `tbaa.struct` metadata can describe which memory subregions in a + /// `memcpy` are padding and what the TBAA tags of the struct are. + /// + /// Note that the fields need not be contiguous. In the following example, + /// there is a 4 byte gap between the two fields. This gap represents padding + /// which does not carry useful data and need not be preserved. + /// + /// !4 = !{ i64 0, i64 4, !1, i64 8, i64 4, !2 } + /// + /// - Parameters: + /// - fields: The fields of the struct. + /// - Returns: A metadata node representing a TBAA struct descriptor. + public func buildTBAAStructNode(_ fields: [TBAAStructField]) -> MDNode { + var ops = [IRMetadata]() + ops.reserveCapacity(fields.count * 3) + let int64 = IntType(width: 64, in: self.context) + for field in fields { + ops.append(MDNode(constant: int64.constant(field.offset.rawValue))) + ops.append(MDNode(constant: int64.constant(field.size.rawValue))) + ops.append(field.type) + } + return MDNode(in: self.context, operands: ops) + } + + /// Builds a TBAA Type Descriptor. + /// + /// Type descriptors describe the type system of the higher level language + /// being compiled and come in two variants: + /// + /// Scalar Type Descriptors + /// ======================= + /// + /// Scalar type descriptors describe types that do not contain other types, + /// such as fixed-width integral and floating-point types. A scalar type + /// has a single parent, which is required to be another scalar type or + /// the TBAA root node. For example, in C, `int32_t` would be described be + /// a scalar type node with a parent pointer to `unsigned char` which, in + /// turn, points to the root for C. + /// + /// ``` + /// +----------+ +------+ +-----------+ + /// | | | | | | + /// | uint32_t +---> char +---> TBAA Root | + /// | | | | | | + /// +----------+ +------+ +-----------+ + /// ``` + /// + /// Struct Type Descriptors + /// ======================= + /// + /// Struct type descriptors describe types that contain a sequence of other + /// type descriptors, at known offsets, as fields. These field type + /// descriptors can either be struct type descriptors themselves or scalar + /// type descriptors. + /// + /// ``` + /// +----------+ + /// | | + /// +-------> uint32_t +----+ + /// | | | | + /// | +----------+ | + /// +------------+ +---v--+ +-----------+ + /// | | | | | | + /// | SomeStruct | | char +---> TBAA Root | + /// | | | | | | + /// +------------+ +---^--+ +-----------+ + /// | +-------+ | + /// | | | | + /// +----------> float +----+ + /// | | + /// +-------+ + /// ``` + /// + /// - Parameters: + /// - parent: The parent type node of this type node or the TBAA root node + /// if it is a top-level entity. + /// - size: The size of the type in bytes. + /// - id: The metadata node whose identity uniquely identifies this node as + /// well. These are often `MDString` values. + /// - fields: The fields of the type, if any. + /// - Returns: A metadata node representing a TBAA type descriptor. + public func buildTBAATypeNode( + _ id: IRMetadata, parent: MDNode, size: Size, fields: [TBAAStructField] = [] + ) -> MDNode { + var ops = [IRMetadata]() + ops.reserveCapacity(3 + fields.count * 3) + let int64 = IntType(width: 64, in: self.context) + ops.append(parent) + ops.append(MDNode(constant: int64.constant(size.rawValue))) + ops.append(id) + for field in fields { + ops.append(field.type) + ops.append(MDNode(constant: int64.constant(field.offset.rawValue))) + ops.append(MDNode(constant: int64.constant(field.size.rawValue))) + } + return MDNode(in: self.context, operands: ops) + } + + /// Builds a TBAA Access Tag. + /// + /// Access tags are metadata nodes attached to `load` and `store` + /// instructions. Access tags use type descriptors to describe the + /// location being accessed in terms of the type system of the higher + /// level language. Access tags are tuples consisting of a base type, + /// an access type and an offset. The base type is a scalar type + /// descriptor or a struct type descriptor, the access type is a + /// scalar type descriptor, and the offset is a constant integer. + /// + /// Tag Structure + /// ============= + /// + /// The access tag `(BaseTy, AccessTy, Offset)` can describe one of two + /// things: + /// + /// - If `BaseTy` is a struct type, the tag describes a memory access + /// (`load` or `store`) of a value of type `AccessTy` contained in + /// the struct type `BaseTy` at offset `Offset`. + /// - If `BaseTy` is a scalar type, `Offset` must be 0 and `BaseTy` and + /// `AccessTy` must be the same; and the access tag describes a scalar + /// access with scalar type `AccessTy`. + /// + /// - Parameters: + /// - baseType: The base type of the access. This is the structure or + /// scalar type that corresponds to the type of the source value in a + /// `load` instruction, or the type of the destination value in a `store` + /// instruction. + /// - accessType: The type of the accessed value. This is the type that + /// corresponds to the type of the destination value in a `load` + /// instruction, or the type of the source value in a `store` instruction. + /// - offset: The ofset of the memory access into the base type. If the + /// base type is scalar, this value must be 0. + /// - size: The size of the access in bytes. + /// - immutable: If true, accesses to this memory are never writes. + /// This corresponds to the `const` memory qualifier in C and C++. + /// - Returns: A metadata node representing a TBAA access tag. + public func buildTBAAAccessTag( + baseType: MDNode, accessType: MDNode, + offset: Size, size: Size, immutable: Bool = false + ) -> MDNode { + let int64 = IntType(width: 64, in: self.context) + let offNode = MDNode(constant: int64.constant(offset.rawValue)) + let sizeNode = MDNode(constant: int64.constant(size.rawValue)) + if immutable { + return MDNode(in: self.context, operands: [ + baseType, + accessType, + offNode, + sizeNode, + MDNode(constant: int64.constant(1)), + ]) + } + return MDNode(in: self.context, operands: [ + baseType, + accessType, + offNode, + sizeNode, + ]) + } + + private func buildAnonymousAARoot(_ name: String = "", _ extra: MDNode? = nil) -> MDNode { + // To ensure uniqueness the root node is self-referential. + let dummy = TemporaryMDNode(in: self.context, operands: []) + var ops = [IRMetadata]() + if let extra = extra { + ops.append(extra) + } + if !name.isEmpty { + ops.append(MDString(name)) + } + let root = MDNode(in: self.context, operands: ops) + // At this point we have + // !0 = metadata !{} <- dummy + // !1 = metadata !{metadata !0} <- root + // Replace the dummy operand with the root node itself and delete the dummy. + dummy.replaceAllUses(with: root) + // We now have + // !1 = metadata !{metadata !1} <- self-referential root + return root + } +} + +// MARK: Irreducible Loop Metadata + +extension MDBuilder { + /// Builds irreducible loop metadata. + /// + /// - Parameters: + /// - weight: The weight of a loop header. + /// - Returns: A metadata node representing the newly created + /// irreducible loop metadata. + public func buildIrreducibleLoopHeaderWeight(_ weight: UInt) -> MDNode { + return MDNode(in: self.context, operands: [ + MDString("loop_header_weight"), + MDNode(constant: IntType(width: 64, in: self.context).constant(weight)) + ]) + } +} diff --git a/Sources/LLVM/MemoryBuffer.swift b/Sources/LLVM/MemoryBuffer.swift index 5e138159..97dbd47e 100644 --- a/Sources/LLVM/MemoryBuffer.swift +++ b/Sources/LLVM/MemoryBuffer.swift @@ -21,6 +21,7 @@ public enum MemoryBufferError: Error { /// position to see if it has reached the end of the file. public class MemoryBuffer: Sequence { let llvm: LLVMMemoryBufferRef + internal var ownsContext: Bool = true /// Creates a `MemoryBuffer` with the contents of `stdin`, stopping once /// `EOF` is read. @@ -110,11 +111,15 @@ public class MemoryBuffer: Sequence { } /// Makes an iterator so this buffer can be traversed in a `for` loop. - public func makeIterator() -> UnsafeBufferPointerIterator { + public func makeIterator() -> UnsafeBufferPointer.Iterator { return UnsafeBufferPointer(start: start, count: size).makeIterator() } + /// Deinitialize this value and dispose of its resources. deinit { + guard self.ownsContext else { + return + } LLVMDisposeMemoryBuffer(llvm) } } diff --git a/Sources/LLVM/MetadataAttributes.swift b/Sources/LLVM/MetadataAttributes.swift new file mode 100644 index 00000000..22e9b2d6 --- /dev/null +++ b/Sources/LLVM/MetadataAttributes.swift @@ -0,0 +1,538 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +/// Source languages known to DWARF. +public enum DWARFSourceLanguage { + /// ISO Ada:1983 + case ada83 + /// ISO Ada:1995 + case ada95 + /// BLISS + case bliss + /// Non-standardized C, e.g. K&R C. + case c + /// ISO C:1989. + case c89 + /// ISO C:1999. + case c99 + /// ISO C:2011 + case c11 + /// ISO C++90 + case cPlusPlus + /// ISO C++03 + case cPlusPlus03 + /// ISO C++11 + case cPlusPlus11 + /// ISO C++14 + case cPlusPlus14 + /// ISO COBOL:1974 + case cobol74 + /// ISO COBOL:1985 + case cobol85 + /// C + case d + /// Dylan + case dylan + /// ISO FORTRAN:1977 + case fortran77 + /// ISO Fortran:1990 + case fortran90 + /// ISO Fortran:1995 + case fortran95 + /// ISO Fortran:2004 + case fortran03 + /// ISO Fortran:2010 + case fortran08 + /// Go + case go + /// Haskell + case haskell + /// Java + case java + /// Julia + case julia + /// ISO Modula-2:1996 + case modula2 + /// Module-3 + case modula3 + /// Objective-C + case objectiveC + /// Objective-C++ + case objectiveCPlusPlus + /// OCaml + case ocaml + /// OpenCL + case openCL + /// ISO Pascal:1983 + case pascal83 + /// ANSI PL/I:1976 + case pli + /// Python + case python + /// RenderScript Kernel Language + case renderScript + /// Rust + case rust + /// Swift + case swift + /// Unified Parallel C + case upc + + // MARK: Vendor Extensions + + /// MIPS Assembler + case mipsAssembler + /// Google RenderScript Kernel Language + case googleRenderScript + /// Borland Delphi + case borlandDelphi + + + private static let languageMapping: [DWARFSourceLanguage: LLVMDWARFSourceLanguage] = [ + .c: LLVMDWARFSourceLanguageC, .c89: LLVMDWARFSourceLanguageC89, + .c99: LLVMDWARFSourceLanguageC99, .c11: LLVMDWARFSourceLanguageC11, + .ada83: LLVMDWARFSourceLanguageAda83, + .cPlusPlus: LLVMDWARFSourceLanguageC_plus_plus, + .cPlusPlus03: LLVMDWARFSourceLanguageC_plus_plus_03, + .cPlusPlus11: LLVMDWARFSourceLanguageC_plus_plus_11, + .cPlusPlus14: LLVMDWARFSourceLanguageC_plus_plus_14, + .cobol74: LLVMDWARFSourceLanguageCobol74, + .cobol85: LLVMDWARFSourceLanguageCobol85, + .fortran77: LLVMDWARFSourceLanguageFortran77, + .fortran90: LLVMDWARFSourceLanguageFortran90, + .pascal83: LLVMDWARFSourceLanguagePascal83, + .modula2: LLVMDWARFSourceLanguageModula2, + .java: LLVMDWARFSourceLanguageJava, + .ada95: LLVMDWARFSourceLanguageAda95, + .fortran95: LLVMDWARFSourceLanguageFortran95, + .pli: LLVMDWARFSourceLanguagePLI, + .objectiveC: LLVMDWARFSourceLanguageObjC, + .objectiveCPlusPlus: LLVMDWARFSourceLanguageObjC_plus_plus, + .upc: LLVMDWARFSourceLanguageUPC, + .d: LLVMDWARFSourceLanguageD, + .python: LLVMDWARFSourceLanguagePython, + .openCL: LLVMDWARFSourceLanguageOpenCL, + .go: LLVMDWARFSourceLanguageGo, + .modula3: LLVMDWARFSourceLanguageModula3, + .haskell: LLVMDWARFSourceLanguageHaskell, + .ocaml: LLVMDWARFSourceLanguageOCaml, + .rust: LLVMDWARFSourceLanguageRust, + .swift: LLVMDWARFSourceLanguageSwift, + .julia: LLVMDWARFSourceLanguageJulia, + .dylan: LLVMDWARFSourceLanguageDylan, + .fortran03: LLVMDWARFSourceLanguageFortran03, + .fortran08: LLVMDWARFSourceLanguageFortran08, + .renderScript: LLVMDWARFSourceLanguageRenderScript, + .bliss: LLVMDWARFSourceLanguageBLISS, + .mipsAssembler: LLVMDWARFSourceLanguageMips_Assembler, + .googleRenderScript: LLVMDWARFSourceLanguageGOOGLE_RenderScript, + .borlandDelphi: LLVMDWARFSourceLanguageBORLAND_Delphi, + ] + + /// Retrieves the corresponding `LLVMDWARFSourceLanguage`. + internal var llvm: LLVMDWARFSourceLanguage { + return DWARFSourceLanguage.languageMapping[self]! + } +} + +/// Enumerates the supported identifying tags for corresponding DWARF +/// Debugging Information Entries (DIEs) known to LLVM. +public enum DWARFTag: UInt32 { + /// Identifies metadata for an array type. + case arrayType = 0x0001 + /// Identifies metadata for a class type. + case classType = 0x0002 + /// Identifies metadata for an alternate entry point. + case entryPoint = 0x0003 + /// Identifies metadata for an enumeration type. + case enumerationType = 0x0004 + /// Identifies metadata for a formal parameter of a parameter list. + case formalParameter = 0x0005 + /// Identifies metadata for an imported declaration. + case importedDeclaration = 0x0008 + /// Identifies metadata for a label in the source; the + /// target of one or more `go to` statements. + case label = 0x000a + /// Identifies metadata for a lexical block in the source (usually for + /// C-like languages). + case lexicalBlock = 0x000b + /// Identifies metadata for a data member. + case member = 0x000d + /// Identifies metadata for a pointer type. + case pointerType = 0x000f + /// Identifies metadata for a reference type + case referenceType = 0x0010 + /// Identifies metadata for a complete compilation unit. + case compileUnit = 0x0011 + /// Identifies metadata for a string type. + case stringType = 0x0012 + /// Identifies metadata for a structure type. + case structureType = 0x0013 + /// Identifies metadata for a subroutine type. + case subroutineType = 0x0015 + /// Identifies metadata for a typedef declaration. + case typedef = 0x0016 + /// Identifies metadata for a union type. + case unionType = 0x0017 + /// Identifies metadata for an unspecified parameter list. Can also be used + /// to identify vararg parameter lists. + case unspecifiedParameters = 0x0018 + /// Identifies metadata for a variant record. + case variant = 0x0019 + /// Identifies metadata for a Fortran common block. + case commonBlock = 0x001a + /// Identifies metadata for a Fortran common inclusion. + case commonInclusion = 0x001b + /// Identifies metadata for an inheritance clause. + case inheritance = 0x001c + /// Identifies metadata for an inlined subroutine. + case inlinedSubroutine = 0x001d + /// Identifies metadata for a module. + case module = 0x001e + /// Identifies metadata for a pointer to a data member. + case ptrToMemberType = 0x001f + /// Identifies metadata for a set type. + case setType = 0x0020 + /// Identifies metadata for a subrange type describing the + /// dimensions of an array. + case subrangeType = 0x0021 + /// Identifies metadata for Pascal and Modula-2's `with` statements. + case withStmt = 0x0022 + /// Identifies metadata for an access declaration. + case accessDeclaration = 0x0023 + /// Identifies metadata for a a base type: a type that is not defined in terms + /// of metadata for other data types. + case baseType = 0x0024 + /// Identifies metadata for the catch block in a `try-catch` statement. + case catchBlock = 0x0025 + /// Identifies metadata for a constant type. + case constType = 0x0026 + /// Identifies metadata for a constant. + case constant = 0x0027 + /// Identifies metadata for an enumerator. + case enumerator = 0x0028 + /// Identifies metadata for a file. + case fileType = 0x0029 + /// Identifies metadata for a C++ `friend` declaration. + case friend = 0x002a + /// Identifies metadata for a Fortran 90 namelist. + case namelist = 0x002b + /// Identifies metadata for an item in a Fortran 90 namelist. + case namelistItem = 0x002c + /// Identifies metadata for an Ada or Pascal packed type. + case packedType = 0x002d + /// Identifies metadata for a subprogram. + case subprogram = 0x002e + /// Identifies metadata for a template type parameter. + case templateTypeParameter = 0x002f + /// Identifies metadata for a template value parameter. + case templateValueParameter = 0x0030 + /// Identifies metadata for the thrown type from a subroutine. + case thrownType = 0x0031 + /// Identifies metadata for the try block in a `try-catch` statement. + case tryBlock = 0x0032 + /// Identifies metadata for a part of a variant record. + case variantPart = 0x0033 + /// Identifies metadata for a variable. + case variable = 0x0034 + /// Identifies metadata for a volatile-qualified type. + case volatileType = 0x0035 + + // MARK: New in DWARF v3 + + /// Identifies metadata for a DWARF procedure. + case dwarfProcedure = 0x0036 + /// Identifies metadata for a restrict-qualified type. + case restrictType = 0x0037 + /// Identifies metadata for a Java interface type. + case interfaceType = 0x0038 + /// Identifies metadata for a namespace. + case namespace = 0x0039 + /// Identifies metadata for an imported module. + case importedModule = 0x003a + /// Identifies metadata for an unspecified type. + case unspecifiedType = 0x003b + /// Identifies metadata for a portion of an object file. + case partialUnit = 0x003c + /// Identifies metadata for an imported compilation unit. + case importedUnit = 0x003d + /// Identifies metadata for a COBOL "level-88" condition that associates a + /// data item, called the conditional variable, with a set of one or more + /// constant values and/or value ranges. + case condition = 0x003f + /// Identifies metadata for a UPC shared-qualified type. + case sharedType = 0x0040 + + // MARK: New in DWARF v4 + + /// Identifies metadata for a single type. + case typeUnit = 0x0041 + /// Identifies metadata for an rvalue-reference-qualified type. + case rvalueReferenceType = 0x0042 + /// Identifies metadata for a template alias. + case templateAlias = 0x0043 + + // MARK: New in DWARF v5 + + /// Identifies metadata for a Fortran "coarray" - an array whose elements + /// are located in different processes rather than in the memory of one + /// process. + case coarrayType = 0x0044 + /// Identifies metadata for a generic subrange. This is useful for arrays of + /// dynamic size in C and Fortran. + case genericSubrange = 0x0045 + /// Identifies metadata for a dynamic type. + case dynamicType = 0x0046 + /// Identifies metadata for an atomic type. + case atomicType = 0x0047 + /// Identifies metadata for a call site. + case callSite = 0x0048 + /// Identifies metadata for a parameter at a call site. + case callSiteParameter = 0x0049 + /// Identifies metadata for the "skeleton" compilation unit in a split DWARF + /// object file. + case skeletonUnit = 0x004a + /// Identifies metadata for an immutable type. + case immutableType = 0x004b + + // MARK: Vendor extensions + + /// Identifies metadata for a MIPS loop. + case mipsLoop = 0x4081 + /// Identifies metadata for a format label. + case formatLabel = 0x4101 + /// Identifies metadata for a function template. + case functionTemplate = 0x4102 + /// Identifies metadata for a class template. + case classTemplate = 0x4103 + /// Identifies metadata for a template template parameter. + case gnuTemplateTemplateParam = 0x4106 + /// Identifies metadata for a template parameter pack. + case gnuTemplateParameterPack = 0x4107 + /// Identifies metadata for a formal parameter pack. + case gnuFormalParameterPack = 0x4108 + /// Identifies metadata for a call site. + case gnuCallSite = 0x4109 + /// Identifies metadata for a call site parameter. + case gnuCallSiteParameter = 0x410a + /// Identifies metadata for an Objective-C property. + case applyProperty = 0x4200 + /// Identifies metadata for an Borland Delphi property. + case borlandProperty = 0xb000 + /// Identifies metadata for an Borland Delphi property. + case borlandDelphiString = 0xb001 + /// Identifies metadata for an Borland Delphi dynamic array. + case borlandDelphiDynamicArray = 0xb002 + /// Identifies metadata for an Borland Delphi set. + case borlandDelphiSet = 0xb003 + /// Identifies metadata for an Borland Delphi variant. + case borlandDelphiVariant = 0xb004 +} + +/// Enumerates the known attributes that can appear on an Objective-C property. +public struct ObjectiveCPropertyAttribute : OptionSet { + public let rawValue: UInt32 + + public init(rawValue: UInt32) { + self.rawValue = rawValue + } + + /// Indicates a property has `readonly` access. + public static let readonly = ObjectiveCPropertyAttribute(rawValue: 0x01) + /// Indicates a property has a customized getter name. + public static let getter = ObjectiveCPropertyAttribute(rawValue: 0x02) + /// Indicates a property has `assign` ownership. + public static let assign = ObjectiveCPropertyAttribute(rawValue: 0x04) + /// Indicates a property has `readwrite` access. + public static let readwrite = ObjectiveCPropertyAttribute(rawValue: 0x08) + /// Indicates a property has `retain` ownership. + public static let retain = ObjectiveCPropertyAttribute(rawValue: 0x10) + /// Indicates a property has `copy` ownership. + public static let copy = ObjectiveCPropertyAttribute(rawValue: 0x20) + /// Indicates a property has `nonatomic` accessors. + public static let nonatomic = ObjectiveCPropertyAttribute(rawValue: 0x40) + /// Indicates a property has a customized setter name. + public static let setter = ObjectiveCPropertyAttribute(rawValue: 0x80) + /// Indicates a property has `atomic` accessors. + public static let atomic = ObjectiveCPropertyAttribute(rawValue: 0x100) + /// Indicates a property has `weak` ownership. + public static let weak = ObjectiveCPropertyAttribute(rawValue: 0x200) + /// Indicates a property has `strong` ownership. + public static let strong = ObjectiveCPropertyAttribute(rawValue: 0x400) + /// Indicates a property has `unsafe_unretained` ownership. + public static let unsafeUnretained = ObjectiveCPropertyAttribute(rawValue: 0x800) + /// Indicates a property has an explicit nullability annotation. + public static let nullability = ObjectiveCPropertyAttribute(rawValue: 0x1000) + /// Indicates a property is null_resettable. + public static let nullResettable = ObjectiveCPropertyAttribute(rawValue: 0x2000) + /// Indicates a property is a `class` property. + public static let `class` = ObjectiveCPropertyAttribute(rawValue: 0x4000) +} + +/// Describes how a base type is encoded and to be interpreted by a debugger. +public enum DIAttributeTypeEncoding { + /// A linear machine address. + case address + /// A true or false value. + case boolean + /// A complex binary floating-point number. + case complexFloat + /// A binary floating-point number. + case float + /// A signed binary integer. + case signed + /// A signed character. + case signedChar + /// An unsigned binary integer. + case unsigned + /// An unsigned character. + case unsignedChar + /// An imaginary binary floating-point number. + case imaginaryFloat + /// A packed decimal number. + case packedDecimal + /// A numeric string. + case numericString + /// An edited string. + case edited + /// A signed fixed-point scaled integer. + case signedFixed + /// An unsigned fixed-point scaled integer. + case unsignedFixed + /// An IEEE-754R decimal floating-point number. + case decimalFloat + /// An ISO/IEC 10646-1:1993 character. + case utf + /// An ISO/IEC 10646-1:1993 character in UCS-4 format. + case ucs + /// An ISO/IEC 646:1991 character. + case ascii + + private static let encodingMapping: [DIAttributeTypeEncoding: LLVMDWARFTypeEncoding] = [ + .address: 0x01, + .boolean: 0x02, + .complexFloat: 0x03, + .float: 0x04, + .signed: 0x05, + .signedChar: 0x06, + .unsigned: 0x07, + .unsignedChar: 0x08, + .imaginaryFloat: 0x09, + .packedDecimal: 0x0a, + .numericString: 0x0b, + .edited: 0x0c, + .signedFixed: 0x0d, + .unsignedFixed: 0x0e, + .decimalFloat: 0x0f, + .utf: 0x10, + .ucs: 0x11, + .ascii: 0x12, + ] + + internal var llvm: LLVMDWARFTypeEncoding { + return DIAttributeTypeEncoding.encodingMapping[self]! + } +} + +/// Enumerates a set of flags that can be applied to metadata nodes to change +/// their interpretation at compile time or attach additional semantic +/// significance at runtime. +public struct DIFlags : OptionSet { + public let rawValue: LLVMDIFlags.RawValue + + public init(rawValue: LLVMDIFlags.RawValue) { + self.rawValue = rawValue + } + + /// Denotes the `private` visibility attribute. + public static let `private` = DIFlags(rawValue: LLVMDIFlagPrivate.rawValue) + /// Denotes the `protected` visibility attribute. + public static let protected = DIFlags(rawValue: LLVMDIFlagProtected.rawValue) + /// Denotes the `public` visibility attribute. + public static let `public` = DIFlags(rawValue: LLVMDIFlagPublic.rawValue) + /// Denotes a forward declaration. + public static let forwardDeclaration = DIFlags(rawValue: LLVMDIFlagFwdDecl.rawValue) + /// Denotes a block object. + public static let appleBlock = DIFlags(rawValue: LLVMDIFlagAppleBlock.rawValue) + /// Denotes a virtual function or dynamic dispatch. + public static let virtual = DIFlags(rawValue: LLVMDIFlagVirtual.rawValue) + /// Denotes a compiler-generated declaration that may not appear in source. + public static let artificial = DIFlags(rawValue: LLVMDIFlagArtificial.rawValue) + /// Denotes an `explicit`-annotated declaration. + public static let explicit = DIFlags(rawValue: LLVMDIFlagExplicit.rawValue) + /// Denotes a prototype declaration. + public static let prototyped = DIFlags(rawValue: LLVMDIFlagPrototyped.rawValue) + /// Denotes an Objective-C class whose definition is visible to the compiler. + public static let objectiveCClassComplete = DIFlags(rawValue: LLVMDIFlagObjcClassComplete.rawValue) + /// Denotes a pointer value that is known to point to a C++ or Objective-C + /// object - usually `self` or `this`. + public static let objectPointer = DIFlags(rawValue: LLVMDIFlagObjectPointer.rawValue) + /// Denotes a vector type. + public static let vector = DIFlags(rawValue: LLVMDIFlagVector.rawValue) + /// Denotes a static member. + public static let staticMember = DIFlags(rawValue: LLVMDIFlagStaticMember.rawValue) + /// Denotes an lvalue reference. + public static let lValueReference = DIFlags(rawValue: LLVMDIFlagLValueReference.rawValue) + /// Denotes an rvalue reference. + public static let rValueReference = DIFlags(rawValue: LLVMDIFlagRValueReference.rawValue) + /// Denotes a class type that is part of a single inheritance class hierarchy. + /// This flag is required to be set for CodeView compatibility. + public static let singleInheritance = DIFlags(rawValue: LLVMDIFlagSingleInheritance.rawValue) + /// Denotes a class type that is part of a multiple inheritance class + /// hierarchy. This flag is required to be set for CodeView compatibility. + public static let multipleInheritance = DIFlags(rawValue: LLVMDIFlagMultipleInheritance.rawValue) + /// Denotes a class type whose inheritance involves virtual members. This + /// flag is required to be set for CodeView compatibility. + public static let virtualInheritance = DIFlags(rawValue: LLVMDIFlagVirtualInheritance.rawValue) + /// Denotes a class type that introduces virtual members. This is needed for + /// the MS C++ ABI does not include all virtual methods from non-primary bases + /// in the vtable for the most derived class + public static let introducedVirtual = DIFlags(rawValue: LLVMDIFlagIntroducedVirtual.rawValue) + /// Denotes a bitfield type. + public static let bitField = DIFlags(rawValue: LLVMDIFlagBitField.rawValue) + /// Denotes a `noreturn` function. + public static let noReturn = DIFlags(rawValue: LLVMDIFlagNoReturn.rawValue) + /// Denotes a parameter that is passed by value according to the target's + /// calling convention. + public static let passByValue = DIFlags(rawValue: LLVMDIFlagTypePassByValue.rawValue) + /// Denotes a parameter that is passed by indirect reference according to the + /// target's calling convention. + public static let passByReference = DIFlags(rawValue: LLVMDIFlagTypePassByReference.rawValue) + /// Denotes a "fixed enum" type e.g. a C++ `enum class`. + public static let enumClass = DIFlags(rawValue: LLVMDIFlagEnumClass.rawValue) + /// Denotes a thunk function. + public static let thunk = DIFlags(rawValue: LLVMDIFlagThunk.rawValue) + /// Denotes a class that has a non-trivial default constructor or is not trivially copiable. + public static let nonTrivial = DIFlags(rawValue: LLVMDIFlagNonTrivial.rawValue) + /// Denotes an indirect virtual base class. + public static let indirectVirtualBase = DIFlags(rawValue: LLVMDIFlagIndirectVirtualBase.rawValue) + /// The mask for `public`, `private`, and `protected` accessibility. + public static let accessibility = DIFlags(rawValue: LLVMDIFlagAccessibility.rawValue) + /// The mask for `singleInheritance`, `multipleInheritance`, + /// and `virtualInheritance`. + public static let pointerToMemberRep = DIFlags(rawValue: LLVMDIFlagPtrToMemberRep.rawValue) + + internal var llvm: LLVMDIFlags { + return LLVMDIFlags(self.rawValue) + } +} + +/// The amount of debug information to emit. +public enum DWARFEmissionKind { + /// No debug information should be emitted. + case none + /// Full debug information should be emitted. + case full + /// Onle line tables should be emitted. + case lineTablesOnly + + private static let emissionMapping: [DWARFEmissionKind: LLVMDWARFEmissionKind] = [ + .none: LLVMDWARFEmissionNone, .full: LLVMDWARFEmissionFull, + .lineTablesOnly: LLVMDWARFEmissionLineTablesOnly, + ] + + internal var llvm: LLVMDWARFEmissionKind { + return DWARFEmissionKind.emissionMapping[self]! + } +} diff --git a/Sources/LLVM/MetadataType.swift b/Sources/LLVM/MetadataType.swift index ae3d389d..c8ba148e 100644 --- a/Sources/LLVM/MetadataType.swift +++ b/Sources/LLVM/MetadataType.swift @@ -18,6 +18,12 @@ public struct MetadataType: IRType { /// Retrieves the underlying LLVM type object. public func asLLVM() -> LLVMTypeRef { - fatalError("This version of LLVM does not support the creation of MetadataType objects") + return LLVMMetadataTypeInContext(context.llvm) + } +} + +extension MetadataType: Equatable { + public static func == (lhs: MetadataType, rhs: MetadataType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() } } diff --git a/Sources/LLVM/Module.swift b/Sources/LLVM/Module.swift index 11392c08..0487dd27 100644 --- a/Sources/LLVM/Module.swift +++ b/Sources/LLVM/Module.swift @@ -2,102 +2,285 @@ import cllvm #endif -/// A `Context` represents execution states for the core LLVM IR system. -public class Context { - internal let llvm: LLVMContextRef - internal let ownsContext: Bool - - /// Retrieves the global context instance. - public static let global = Context(llvm: LLVMGetGlobalContext()!) - - /// Creates a `Context` object using `LLVMContextCreate` - public init() { - llvm = LLVMContextCreate() - ownsContext = true - } - - /// Creates a `Context` object from an `LLVMContextRef` object. - public init(llvm: LLVMContextRef, ownsContext: Bool = false) { - self.llvm = llvm - self.ownsContext = ownsContext - } - - deinit { - if ownsContext { - LLVMContextDispose(llvm) - } - } -} - -/// Represents the possible errors that can be thrown while interacting with a -/// `Module` object. -public enum ModuleError: Error, CustomStringConvertible { - /// Thrown when a module does not pass the module verification process. - /// Includes the reason the module did not pass verification. - case didNotPassVerification(String) - /// Thrown when a module cannot be printed at a given path. Provides the - /// erroneous path and a deeper reason why printing to that path failed. - case couldNotPrint(path: String, error: String) - /// Thrown when a module cannot emit bitcode because it contains erroneous - /// declarations. - case couldNotEmitBitCode(path: String) - - public var description: String { - switch self { - case .didNotPassVerification(let message): - return "module did not pass verification: \(message)" - case .couldNotPrint(let path, let error): - return "could not print to file \(path): \(error)" - case .couldNotEmitBitCode(let path): - return "could not emit bitcode to file \(path) for an unknown reason" - } - } -} - /// A `Module` represents the top-level structure of an LLVM program. An LLVM /// module is effectively a translation unit or a collection of translation /// units merged together. +/// +/// LLVM programs are composed of `Module`s consisting of functions, global +/// variables, symbol table entries, and metadata. Modules may be combined +/// together with the LLVM linker, which merges function (and global variable) +/// definitions, resolves forward declarations, and merges symbol table entries. +/// +/// Creating a Module +/// ================== +/// +/// A module can be created using `init(name:context:)`. +/// Note that the default target triple is bare metal and there is no default data layout. +/// If you require these to be specified (e.g. to increase the correctness of default alignment values), +/// be sure to set them yourself. +/// +/// if let machine = try? TargetMachine() { +/// module.targetTriple = machine.triple +/// module.dataLayout = machine.dataLayout +/// } +/// +/// Verifying a Module +/// ================== +/// +/// A module naturally grows to encompass a large amount of data during code +/// generation. To verify that the module is well-formed and suitable for +/// submission to later phases of LLVM, call `Module.verify()`. If the module +/// does not pass verification, an error describing the cause will be thrown. +/// +/// let module = Module(name: "Example") +/// let builder = IRBuilder(module: module) +/// let main = builder.addFunction("main", +/// type: FunctionType([], VoidType())) +/// let entry = main.appendBasicBlock(named: "entry") +/// builder.positionAtEnd(of: entry) +/// builder.buildRet(main.address(of: entry)!) +/// +/// try module.verify() +/// // The following error is thrown: +/// // module did not pass verification: blockaddress may not be used with the entry block! +/// // Found return instr that returns non-void in Function of void return type! +/// +/// The built-in verifier attempts to be correct at the cost of completeness. +/// For strictest checking, invoke the `lli` tool on any IR that is generated. +/// +/// Threading Considerations +/// ======================== +/// +/// A module value is associated with exactly one LLVM context. That context, +/// and its creating thread, must be used to access and mutate this module as +/// LLVM provides no locking or atomicity guarantees. +/// +/// Printing The Contents of a Module +/// ================================= +/// +/// The contents of a module are mostly machine-independent. It is often useful +/// while debugging to view this machine-independent IR. A module responds to +/// `Module.dump()` by printing this representation to standard output. To +/// dump the module to a file, use `Module.print(to:)`. In general, a module +/// must be associated with a `TargetMachine` and a target environment for its +/// contents to be fully useful for export to later file formats such as object +/// files or bitcode. See `TargetMachine.emitToFile(module:type:path)` for more +/// details. +/// +/// Module Flags +/// ============ +/// +/// To convey information about a module to LLVM's various subsystems, a module +/// may have flags attached. These flags are keyed by global strings, and +/// attached as metadata to the module with the privileged `llvm.module.flags` +/// metadata identifier. Certain flags have hard-coded meanings in LLVM such as +/// the Objective-C garbage collection flags or the linker options flags. Most +/// other flags are stripped from any resulting object files. public final class Module: CustomStringConvertible { internal let llvm: LLVMModuleRef + internal var ownsContext: Bool = true + + /// Returns the context associated with this module. + public let context: Context + /// Creates a `Module` with the given name. /// /// - parameter name: The name of the module. /// - parameter context: The context to associate this module with. If no - /// context is provided, one will be inferred. - public init(name: String, context: Context? = nil) { + /// context is provided, the global context is assumed. + public init(name: String, context: Context = .global) { // Ensure the LLVM initializer is called when the first module is created initializeLLVM() - if let context = context { - llvm = LLVMModuleCreateWithNameInContext(name, context.llvm) - self.context = context - } else { - llvm = LLVMModuleCreateWithName(name) - self.context = Context(llvm: LLVMGetModuleContext(llvm)!) + self.llvm = LLVMModuleCreateWithNameInContext(name, context.llvm) + self.context = context + } + + + /// Deinitialize this value and dispose of its resources. + deinit { + guard self.ownsContext else { + return } + LLVMDisposeModule(llvm) } - /// Returns the context associated with this module. - public let context: Context + /// Obtain the target triple for this module. + public var targetTriple: Triple { + get { + guard let id = LLVMGetTarget(llvm) else { return Triple("") } + return Triple(String(cString: id)) + } + set { LLVMSetTarget(llvm, newValue.data) } + } /// Obtain the data layout for this module. public var dataLayout: TargetData { - return TargetData(llvm: LLVMGetModuleDataLayout(llvm)) + get { return TargetData(llvm: LLVMGetModuleDataLayout(llvm)) } + set { LLVMSetModuleDataLayout(llvm, newValue.llvm) } + } + + /// Returns a string describing the data layout associated with this module. + public var dataLayoutString: String { + get { + guard let id = LLVMGetDataLayoutStr(llvm) else { return "" } + return String(cString: id) + } + set { LLVMSetDataLayout(llvm, newValue) } } /// The identifier of this module. public var name: String { get { - guard let id = LLVMGetModuleIdentifier(llvm, nil) else { return "" } + var count = 0 + guard let id = LLVMGetModuleIdentifier(llvm, &count) else { return "" } return String(cString: id) } set { LLVMSetModuleIdentifier(llvm, newValue, newValue.utf8.count) } } + + /// The source filename of this module. + /// + /// The source filename appears at the top of an IR module: + /// + /// source_filename = "/path/to/source.c" + /// + /// Local functions used in profile data prepend the source file name to the local function name. + /// + /// If not otherwise set, `name` is used. + public var sourceFileName: String { + get { + var count = 0 + guard let fn = LLVMGetSourceFileName(llvm, &count) else { return "" } + return String(cString: fn) + } + set { + LLVMSetSourceFileName(llvm, newValue, newValue.utf8.count) + } + } + + /// Retrieves the inline assembly for this module, if any. + public var inlineAssembly: String { + get { + var length: Int = 0 + guard let id = LLVMGetModuleInlineAsm(llvm, &length) else { return "" } + return String(cString: id) + } + set { + LLVMSetModuleInlineAsm2(llvm, newValue, newValue.utf8.count) + } + } + + /// Retrieves the sequence of functions that make up this module. + public var functions: AnySequence { + var current = firstFunction + return AnySequence { + return AnyIterator { + defer { current = current?.next() } + return current + } + } + } + + /// Retrieves the first function in this module, if there are any functions. + public var firstFunction: Function? { + guard let fn = LLVMGetFirstFunction(llvm) else { return nil } + return Function(llvm: fn) + } + + /// Retrieves the last function in this module, if there are any functions. + public var lastFunction: Function? { + guard let fn = LLVMGetLastFunction(llvm) else { return nil } + return Function(llvm: fn) + } + + /// Retrieves the first global in this module, if there are any globals. + public var firstGlobal: Global? { + guard let fn = LLVMGetFirstGlobal(llvm) else { return nil } + return Global(llvm: fn) + } + + /// Retrieves the last global in this module, if there are any globals. + public var lastGlobal: Global? { + guard let fn = LLVMGetLastGlobal(llvm) else { return nil } + return Global(llvm: fn) + } + + /// Retrieves the sequence of functions that make up this module. + public var globals: AnySequence { + var current = firstGlobal + return AnySequence { + return AnyIterator { + defer { current = current?.next() } + return current + } + } + } + + /// Retrieves the first alias in this module, if there are any aliases. + public var firstAlias: Alias? { + guard let fn = LLVMGetFirstGlobalAlias(llvm) else { return nil } + return Alias(llvm: fn) + } + + /// Retrieves the last alias in this module, if there are any aliases. + public var lastAlias: Alias? { + guard let fn = LLVMGetLastGlobalAlias(llvm) else { return nil } + return Alias(llvm: fn) + } + + /// Retrieves the sequence of aliases that make up this module. + public var aliases: AnySequence { + var current = firstAlias + return AnySequence { + return AnyIterator { + defer { current = current?.next() } + return current + } + } + } + + /// Retrieves the first alias in this module, if there are any aliases. + public var firstNamedMetadata: NamedMetadata? { + guard let fn = LLVMGetFirstNamedMetadata(llvm) else { return nil } + return NamedMetadata(module: self, llvm: fn) + } + + /// Retrieves the last alias in this module, if there are any aliases. + public var lastNamedMetadata: NamedMetadata? { + guard let fn = LLVMGetLastNamedMetadata(llvm) else { return nil } + return NamedMetadata(module: self, llvm: fn) + } + + /// Retrieves the sequence of aliases that make up this module. + public var namedMetadata: AnySequence { + var current = firstNamedMetadata + return AnySequence { + return AnyIterator { + defer { current = current?.next() } + return current + } + } + } + + /// The current debug metadata version number. + public static var debugMetadataVersion: UInt32 { + return LLVMDebugMetadataVersion(); + } + + /// The version of debug metadata that's present in this module. + public var debugMetadataVersion: UInt32 { + return LLVMGetModuleDebugMetadataVersion(self.llvm) + } +} + +// MARK: Module Printing +extension Module { /// Print a representation of a module to a file at the given path. /// /// If the provided path is not suitable for writing, this function will throw @@ -117,6 +300,22 @@ public final class Module: CustomStringConvertible { } } + /// Dump a representation of this module to stderr. + public func dump() { + LLVMDumpModule(llvm) + } + + /// The full text IR of this module + public var description: String { + let cStr = LLVMPrintModuleToString(llvm)! + defer { LLVMDisposeMessage(cStr) } + return String(cString: cStr) + } +} + +// MARK: Module Emission + +extension Module { /// Writes the bitcode of elements in this module to a file at the given path. /// /// If the provided path is not suitable for writing, this function will throw @@ -134,7 +333,11 @@ public final class Module: CustomStringConvertible { throw ModuleError.couldNotEmitBitCode(path: path) } } +} + +// MARK: Module Actions +extension Module { /// Verifies that this module is valid, taking the specified action if not. /// If this module did not pass verification, a description of any invalid /// constructs is provided with the thrown @@ -148,66 +351,433 @@ public final class Module: CustomStringConvertible { } } - /// Retrieves the sequence of functions that make up this module. - public var functions: AnySequence { - var current = firstFunction - return AnySequence { - return AnyIterator { - defer { current = current?.next() } - return current + /// Links the given module with this module. If the link succeeds, this + /// module will the composite of the two input modules. + /// + /// The result of this function is `true` if the link succeeds, or `false` + /// otherwise. + /// + /// - parameter other: The module to link with this module. + public func link(_ other: Module) -> Bool { + // First clone the other module; `LLVMLinkModules2` consumes the source + // module via a move and that module still owns its ModuleRef. + let otherClone = LLVMCloneModule(other.llvm) + // N.B. Returns `true` on error. + return LLVMLinkModules2(self.llvm, otherClone) == 0 + } + + + /// Strip debug info in the module if it exists. + /// + /// To do this, we remove all calls to the debugger intrinsics and any named + /// metadata for debugging. We also remove debug locations for instructions. + /// Return true if module is modified. + public func stripDebugInfo() -> Bool { + return LLVMStripModuleDebugInfo(self.llvm) != 0 + } +} + +// MARK: Global Declarations + +extension Module { + /// Searches for and retrieves a global variable with the given name in this + /// module if that name references an existing global variable. + /// + /// - parameter name: The name of the global to reference. + /// + /// - returns: A value representing the referenced global if it exists. + public func global(named name: String) -> Global? { + guard let ref = LLVMGetNamedGlobal(llvm, name) else { return nil } + return Global(llvm: ref) + } + + /// Searches for and retrieves a type with the given name in this module if + /// that name references an existing type. + /// + /// - parameter name: The name of the type to create. + /// + /// - returns: A representation of the newly created type with the given name + /// or nil if such a representation could not be created. + public func type(named name: String) -> IRType? { + guard let type = LLVMGetTypeByName(llvm, name) else { return nil } + return convertType(type) + } + + /// Searches for and retrieves a function with the given name in this module + /// if that name references an existing function. + /// + /// - parameter name: The name of the function to create. + /// + /// - returns: A representation of a function with the given + /// name or nil if such a representation could not be created. + public func function(named name: String) -> Function? { + guard let fn = LLVMGetNamedFunction(llvm, name) else { return nil } + return Function(llvm: fn) + } + + /// Searches for and retrieves an intrinsic with the given name in this module + /// if that name references an intrinsic. + /// + /// - Parameters: + /// - name: The name of the intrinsic to search for. + /// - parameters: The type of the parameters of the intrinsic to resolve any + /// ambiguity caused by overloads. + /// - returns: A representation of an intrinsic with the given name or nil + /// if such an intrinsic could not be found. + public func intrinsic(named name: String, parameters: [IRType] = []) -> Intrinsic? { + guard let intrinsic = self.function(named: name) else { + return nil + } + + let index = LLVMGetIntrinsicID(intrinsic.asLLVM()) + guard index != 0 else { return nil } + + guard LLVMIntrinsicIsOverloaded(index) != 0 else { + return Intrinsic(llvm: intrinsic.asLLVM()) + } + + var argIRTypes = parameters.map { $0.asLLVM() as Optional } + return argIRTypes.withUnsafeMutableBufferPointer { buf -> Intrinsic in + guard let value = LLVMGetIntrinsicDeclaration(self.llvm, index, buf.baseAddress, parameters.count) else { + fatalError("Could not retrieve type of intrinsic") } + return Intrinsic(llvm: value) } } - /// Retrieves the first function in this module, if there are any functions. - public var firstFunction: Function? { - guard let fn = LLVMGetFirstFunction(llvm) else { return nil } - return Function(llvm: fn) + /// Searches for and retrieves an intrinsic with the given selector in this + /// module if that selector references an intrinsic. + /// + /// Unlike `Module.intrinsic(named:parameters:)`, the intrinsic function need + /// not be declared. If the module contains a declaration of the intrinsic + /// function, it will be returned. Else, a declaration for the intrinsic + /// will be created and appended to this module. + /// + /// LLVMSwift intrinsic selector syntax differs from the LLVM naming + /// conventions for intrinsics in one crucial way: all dots are replaced by + /// underscores. + /// + /// For example: + /// + /// llvm.foo.bar.baz -> Intrinsic.ID.llvm_foo_bar_baz + /// llvm.sin -> Intrinsic.ID.llvm_sin + /// llvm.stacksave -> Intrinsic.ID.llvm_stacksave + /// llvm.x86.xsave64 -> Intrinsic.ID.llvm_x86_xsave64 + /// + /// - Parameters: + /// - selector: The selector of the intrinsic to search for. + /// - parameters: The type of the parameters of the intrinsic to resolve any + /// ambiguity caused by overloads. + /// - returns: A representation of an intrinsic with the given name or nil + /// if such an intrinsic could not be found. + public func intrinsic(_ selector: Intrinsic.Selector, parameters: [IRType] = []) -> Intrinsic? { + var argIRTypes = parameters.map { $0.asLLVM() as Optional } + return argIRTypes.withUnsafeMutableBufferPointer { buf -> Intrinsic in + guard let value = LLVMGetIntrinsicDeclaration(self.llvm, selector.index, buf.baseAddress, parameters.count) else { + fatalError("Could not retrieve type of intrinsic") + } + return Intrinsic(llvm: value) + } } - /// Retrieves the last function in this module, if there are any functions. - public var lastFunction: Function? { - guard let fn = LLVMGetLastFunction(llvm) else { return nil } - return Function(llvm: fn) + + /// Searches for and retrieves an alias with the given name in this module + /// if that name references an existing alias. + /// + /// - parameter name: The name of the alias to search for. + /// + /// - returns: A representation of an alias with the given + /// name or nil if no such named alias exists. + public func alias(named name: String) -> Alias? { + guard let alias = LLVMGetNamedGlobalAlias(llvm, name, name.count) else { return nil } + return Alias(llvm: alias) } - /// Retrieves the first global in this module, if there are any globals. - public var firstGlobal: Global? { - guard let fn = LLVMGetFirstGlobal(llvm) else { return nil } - return Global(llvm: fn) + /// Searches for and retrieves a comdat section with the given name in this + /// module. If none is found, one with that name is created and returned. + /// + /// - parameter name: The name of the comdat section to create. + /// + /// - returns: A representation of the newly created comdat section with the + /// given name. + public func comdat(named name: String) -> Comdat { + guard let comdat = LLVMGetOrInsertComdat(llvm, name) else { fatalError() } + return Comdat(llvm: comdat) } - /// Retrieves the last global in this module, if there are any globals. - public var lastGlobal: Global? { - guard let fn = LLVMGetLastGlobal(llvm) else { return nil } - return Global(llvm: fn) + /// Searches for and retrieves module-level named metadata with the given name + /// in this module. If none is found, one with that name is created and + /// returned. + /// + /// - parameter name: The name of the comdat section to create. + /// + /// - returns: A representation of the newly created metadata with the + /// given name. + public func metadata(named name: String) -> NamedMetadata { + return NamedMetadata(module: self, llvm: LLVMGetOrInsertNamedMetadata(self.llvm, name, name.count)) } - /// Retrieves the sequence of functions that make up this module. - public var globals: AnySequence { - var current = firstGlobal - return AnySequence { - return AnyIterator { - defer { current = current?.next() } - return current + /// Build a named function body with the given type. + /// + /// - parameter name: The name of the newly defined function. + /// - parameter type: The type of the newly defined function. + /// + /// - returns: A value representing the newly inserted function definition. + public func addFunction(_ name: String, type: FunctionType) -> Function { + return Function(llvm: LLVMAddFunction(self.llvm, name, type.asLLVM())) + } + + /// Build a named global of the given type. + /// + /// - parameter name: The name of the newly inserted global value. + /// - parameter type: The type of the newly inserted global value. + /// - parameter addressSpace: The optional address space where the global + /// variable resides. + /// + /// - returns: A value representing the newly inserted global variable. + public func addGlobal(_ name: String, type: IRType, addressSpace: AddressSpace = .zero) -> Global { + guard let val = LLVMAddGlobalInAddressSpace(llvm, type.asLLVM(), name, UInt32(addressSpace.rawValue)) else { + fatalError() + } + return Global(llvm: val) + } + + /// Build a named global of the given type. + /// + /// - parameter name: The name of the newly inserted global value. + /// - parameter initializer: The initial value for the global variable. + /// - parameter addressSpace: The optional address space where the global + /// variable resides. + /// + /// - returns: A value representing the newly inserted global variable. + public func addGlobal(_ name: String, initializer: IRValue, addressSpace: AddressSpace = .zero) -> Global { + let global = addGlobal(name, type: initializer.type) + global.initializer = initializer + return global + } + + /// Build a named global string consisting of an array of `i8` type filled in + /// with the nul terminated string value. + /// + /// - parameter name: The name of the newly inserted global string value. + /// - parameter value: The character contents of the newly inserted global. + /// + /// - returns: A value representing the newly inserted global string variable. + public func addGlobalString(name: String, value: String) -> Global { + let length = value.utf8.count + + var global = addGlobal(name, type: + ArrayType(elementType: IntType.int8, count: length + 1)) + + global.alignment = Alignment(1) + global.initializer = value + + return global + } + + /// Build a named alias to a global value or a constant expression. + /// + /// Aliases, unlike function or variables, don’t create any new data. They are + /// just a new symbol and metadata for an existing position. + /// + /// - parameter name: The name of the newly inserted alias. + /// - parameter aliasee: The value or constant to alias. + /// - parameter type: The type of the aliased value or expression. + /// + /// - returns: A value representing the newly created alias. + public func addAlias(name: String, to aliasee: IRGlobal, type: IRType) -> Alias { + return Alias(llvm: LLVMAddAlias(llvm, type.asLLVM(), aliasee.asLLVM(), name)) + } + + /// Append to the module-scope inline assembly blocks. + /// + /// A trailing newline is added if the given string doesn't have one. + /// + /// - parameter asm: The inline assembly expression template string. + public func appendInlineAssembly(_ asm: String) { + LLVMAppendModuleInlineAsm(llvm, asm, asm.count) + } +} + +// MARK: Module Flags + +extension Module { + /// Represents flags that describe information about the module for use by + /// an external entity e.g. the dynamic linker. + /// + /// - Warning: Module flags are not a general runtime metadata infrastructure, + /// and may be stripped by LLVM. As of the current release, LLVM hardcodes + /// support for object-file emission of module flags related to + /// Objective-C. + public class Flags { + /// Enumerates the supported behaviors for resolving collisions when two + /// module flags share the same key. These collisions can occur when the + /// different flags are inserted under the same key, or when modules + /// containing flags under the same key are merged. + public enum Behavior { + /// Emits an error if two values disagree, otherwise the resulting value + /// is that of the operands. + case error + /// Emits a warning if two values disagree. The result value will be the + /// operand for the flag from the first module being linked. + case warning + /// Adds a requirement that another module flag be present and have a + /// specified value after linking is performed. The value must be a + /// metadata pair, where the first element of the pair is the ID of the + /// module flag to be restricted, and the second element of the pair is + /// the value the module flag should be restricted to. This behavior can + /// be used to restrict the allowable results (via triggering of an error) + /// of linking IDs with the **Override** behavior. + case require + /// Uses the specified value, regardless of the behavior or value of the + /// other module. If both modules specify **Override**, but the values + /// differ, an error will be emitted. + case override + /// Appends the two values, which are required to be metadata nodes. + case append + /// Appends the two values, which are required to be metadata + /// nodes. However, duplicate entries in the second list are dropped + /// during the append operation. + case appendUnique + + fileprivate init(raw: LLVMModuleFlagBehavior) { + switch raw { + case LLVMModuleFlagBehaviorError: + self = .error + case LLVMModuleFlagBehaviorWarning: + self = .warning + case LLVMModuleFlagBehaviorRequire: + self = .require + case LLVMModuleFlagBehaviorOverride: + self = .override + case LLVMModuleFlagBehaviorAppend: + self = .append + case LLVMModuleFlagBehaviorAppendUnique: + self = .appendUnique + default: + fatalError("Unknown behavior kind") + } + } + + fileprivate static let behaviorMapping: [Behavior: LLVMModuleFlagBehavior] = [ + .error: LLVMModuleFlagBehaviorError, + .warning: LLVMModuleFlagBehaviorWarning, + .require: LLVMModuleFlagBehaviorRequire, + .override: LLVMModuleFlagBehaviorOverride, + .append: LLVMModuleFlagBehaviorAppend, + .appendUnique: LLVMModuleFlagBehaviorAppendUnique, + ] + } + + /// Represents an entry in the module flags structure. + public struct Entry { + fileprivate let base: Flags + fileprivate let index: UInt32 + + /// The conflict behavior of this flag. + public var behavior: Behavior { + let raw = LLVMModuleFlagEntriesGetFlagBehavior(self.base.llvm, self.index) + return Behavior(raw: raw) + } + + /// The key this flag was inserted with. + public var key: String { + var count = 0 + guard let key = LLVMModuleFlagEntriesGetKey(self.base.llvm, self.index, &count) else { return "" } + return String(cString: key) + } + + /// The metadata value associated with this flag. + public var metadata: IRMetadata { + return AnyMetadata(llvm: LLVMModuleFlagEntriesGetMetadata(self.base.llvm, self.index)) } } + + private let llvm: OpaquePointer? + private let bounds: Int + fileprivate init(llvm: OpaquePointer?, bounds: Int) { + self.llvm = llvm + self.bounds = bounds + } + + /// Deinitialize this value and dispose of its resources. + deinit { + guard let ptr = llvm else { return } + LLVMDisposeModuleFlagsMetadata(ptr) + } + + /// Retrieves a flag at the given index. + /// + /// - Parameter index: The index to retrieve. + /// + /// - Returns: An entry describing the flag at the given index. + public subscript(_ index: Int) -> Entry { + precondition(index >= 0 && index < self.bounds, "Index out of bounds") + return Entry(base: self, index: UInt32(index)) + } + + /// Returns the number of module flag metadata entries. + public var count: Int { + return self.bounds + } } - /// Dump a representation of this module to stderr. - public func dump() { - LLVMDumpModule(llvm) + /// Add a module-level flag to the module-level flags metadata. + /// + /// - Parameters: + /// - name: The key for this flag. + /// - value: The metadata node to insert as the value for this flag. + /// - behavior: The resolution strategy to apply should the key for this + /// flag conflict with an existing flag. + public func addFlag(named name: String, value: IRMetadata, behavior: Flags.Behavior) { + let raw = Flags.Behavior.behaviorMapping[behavior]! + LLVMAddModuleFlag(llvm, raw, name, name.count, value.asMetadata()) } - /// The full text IR of this module - public var description: String { - let cStr = LLVMPrintModuleToString(llvm)! - defer { LLVMDisposeMessage(cStr) } - return String(cString: cStr) + /// A convenience for inserting constant values as module-level flags. + /// + /// - Parameters: + /// - name: The key for this flag. + /// - value: The constant value to insert as the metadata for this flag. + /// - behavior: The resolution strategy to apply should the key for this + /// flag conflict with an existing flag. + public func addFlag(named name: String, constant: IRConstant, behavior: Flags.Behavior) { + let raw = Flags.Behavior.behaviorMapping[behavior]! + LLVMAddModuleFlag(llvm, raw, name, name.count, LLVMValueAsMetadata(constant.asLLVM())) } - deinit { - LLVMDisposeModule(llvm) + /// Retrieves the module-level flags, if they exist. + public var flags: Flags? { + var len = 0 + guard let raw = LLVMCopyModuleFlagsMetadata(llvm, &len) else { return nil } + return Flags(llvm: raw, bounds: len) + } +} + +// MARK: Module Errors + +/// Represents the possible errors that can be thrown while interacting with a +/// `Module` object. +public enum ModuleError: Error, CustomStringConvertible { + /// Thrown when a module does not pass the module verification process. + /// Includes the reason the module did not pass verification. + case didNotPassVerification(String) + /// Thrown when a module cannot be printed at a given path. Provides the + /// erroneous path and a deeper reason why printing to that path failed. + case couldNotPrint(path: String, error: String) + /// Thrown when a module cannot emit bitcode because it contains erroneous + /// declarations. + case couldNotEmitBitCode(path: String) + + public var description: String { + switch self { + case .didNotPassVerification(let message): + return "module did not pass verification: \(message)" + case .couldNotPrint(let path, let error): + return "could not print to file \(path): \(error)" + case .couldNotEmitBitCode(let path): + return "could not emit bitcode to file \(path) for an unknown reason" + } } } diff --git a/Sources/LLVM/NamedMetadata.swift b/Sources/LLVM/NamedMetadata.swift new file mode 100644 index 00000000..118c9110 --- /dev/null +++ b/Sources/LLVM/NamedMetadata.swift @@ -0,0 +1,63 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +/// A `NamedMetadata` object represents a module-level metadata value identified +/// by a user-provided name. Named metadata is generated lazily when operands +/// are attached. +public class NamedMetadata { + /// The module with which this named metadata is associated. + public let module: Module + /// The name associated with this named metadata. + public let name: String + + private let llvm: LLVMNamedMDNodeRef + + init(module: Module, llvm: LLVMNamedMDNodeRef) { + self.module = module + self.llvm = llvm + var nameLen = 0 + guard let rawName = LLVMGetNamedMetadataName(llvm, &nameLen) else { + fatalError("Could not retrieve name for named MD node?") + } + self.name = String(cString: rawName) + } + + /// Retrieves the previous alias in the module, if there is one. + public func previous() -> NamedMetadata? { + guard let previous = LLVMGetPreviousNamedMetadata(llvm) else { return nil } + return NamedMetadata(module: self.module, llvm: previous) + } + + /// Retrieves the next alias in the module, if there is one. + public func next() -> NamedMetadata? { + guard let next = LLVMGetNextNamedMetadata(llvm) else { return nil } + return NamedMetadata(module: self.module,llvm: next) + } + + /// Computes the operands of a named metadata node. + public var operands: [IRMetadata] { + let count = Int(LLVMGetNamedMetadataNumOperands(self.module.llvm, name)) + let operands = UnsafeMutablePointer.allocate(capacity: count) + LLVMGetNamedMetadataOperands(self.module.llvm, name, operands) + + var ops = [IRMetadata]() + ops.reserveCapacity(count) + for i in 0..? + self.llvm = LLVMCreateBinary(memoryBuffer.llvm, context.llvm, &error) + if let error = error { + defer { LLVMDisposeMessage(error) } + throw BinaryFileError.couldNotCreate(String(cString: error)) + } + self.kind = Kind(llvm: LLVMBinaryGetType(self.llvm)) + self.buffer = memoryBuffer + } + + /// Creates an `ObjectFile` with the contents of the object file at + /// the provided path. + /// - parameter path: The absolute file path on your filesystem. + /// - throws: `MemoryBufferError` or `BinaryFileError` if there was an error + /// on creation + public convenience init(path: String) throws { + let memoryBuffer = try MemoryBuffer(contentsOf: path) + try self.init(memoryBuffer: memoryBuffer) + } + + + /// Deinitialize this value and dispose of its resources. + deinit { + LLVMDisposeBinary(llvm) + } +} + /// An in-memory representation of a format-independent object file. -public class ObjectFile { - let llvm: LLVMObjectFileRef - - /// Creates an `ObjectFile` with the contents of a provided memory buffer. - /// - parameter memoryBuffer: A memory buffer containing a valid binary - /// object file. - public init?(memoryBuffer: MemoryBuffer) { - guard let file = LLVMCreateObjectFile(memoryBuffer.llvm) else { - return nil - } - self.llvm = file +public class ObjectFile: BinaryFile { + override init(llvm: LLVMBinaryRef, buffer: MemoryBuffer) { + super.init(llvm: llvm, buffer: buffer) + precondition(self.kind != .machOUniversalBinary, + "File format is not an object file; use MachOUniversalBinaryFile instead") + } + + /// Creates an object file with the contents of a provided memory buffer. + /// + /// - Parameters: + /// - memoryBuffer: A memory buffer containing a valid object file. + /// - context: The context to allocate the given binary in. + /// - throws: `BinaryFileError` if there was an error on creation. + public override init(memoryBuffer: MemoryBuffer, in context: Context = .global) throws { + try super.init(memoryBuffer: memoryBuffer, in: context) + precondition(self.kind != .machOUniversalBinary, + "File format is not an object file; use MachOUniversalBinaryFile instead") + } + + /// Returns a sequence of all the sections in this object file. + public var sections: SectionSequence { + return SectionSequence(llvm: LLVMObjectFileCopySectionIterator(llvm), object: self) + } + + /// Returns a sequence of all the symbols in this object file. + public var symbols: SymbolSequence { + return SymbolSequence(llvm: LLVMObjectFileCopySymbolIterator(llvm), object: self) + } +} + +/// An in-memory representation of a Mach-O universal binary file. +public final class MachOUniversalBinaryFile: BinaryFile { + /// Creates an `MachOUniversalBinaryFile` with the contents of the object file at + /// the provided path. + /// - parameter path: The absolute file path on your filesystem. + /// - throws: `MemoryBufferError` or `BinaryFileError` if there was an error + /// on creation + public convenience init(path: String) throws { + let memoryBuffer = try MemoryBuffer(contentsOf: path) + try self.init(memoryBuffer: memoryBuffer) + } + + /// Creates a Mach-O universal binary file with the contents of a provided + /// memory buffer. + /// + /// - Parameters: + /// - memoryBuffer: A memory buffer containing a valid universal Mach-O file. + /// - context: The context to allocate the given binary in. + /// - throws: `BinaryFileError` if there was an error on creation. + public override init(memoryBuffer: MemoryBuffer, in context: Context = .global) throws { + try super.init(memoryBuffer: memoryBuffer, in: context) + guard self.kind == .machOUniversalBinary else { + throw BinaryFileError.couldNotCreate("File is not a Mach-O universal binary") } + } - /// Creates an `ObjectFile` with the contents of the object file at - /// the provided path. - /// - parameter path: The absolute file path on your filesystem. - public convenience init?(path: String) { - - guard let memoryBuffer = try? MemoryBuffer(contentsOf: path) else { - return nil - } - self.init(memoryBuffer: memoryBuffer) + /// Retrieves the object file for a specific architecture, if it exists. + /// + /// - Parameters: + /// - architecture: The architecture of a Mach-O file contained in this + /// universal binary file. + /// - Returns: An object file for the given architecture if it exists. + /// - throws: `BinaryFileError` if there was an error on creation. + public func objectFile(for architecture: Triple.Architecture) throws -> Slice { + var error: UnsafeMutablePointer? + let archName = architecture.rawValue + let archFile: LLVMBinaryRef = LLVMMachOUniversalBinaryCopyObjectForArch(self.llvm, archName, archName.count, &error) + if let error = error { + defer { LLVMDisposeMessage(error) } + throw BinaryFileError.couldNotCreate(String(cString: error)) } + let buffer = MemoryBuffer(llvm: LLVMBinaryCopyMemoryBuffer(archFile)) + return Slice(parent: self, llvm: archFile, buffer: buffer) + } + + /// Represents an architecture-specific slice of a Mach-O universal binary + /// file. + public final class Slice: ObjectFile { + // Maintain a strong reference to our parent binary so the backing buffer + // doesn't disappear on us. + private let parent: MachOUniversalBinaryFile - /// Returns a sequence of all the sections in this object file. - public var sections: SectionSequence { - return SectionSequence(llvm: LLVMGetSections(llvm), object: self) + fileprivate init(parent: MachOUniversalBinaryFile, llvm: LLVMBinaryRef, buffer: MemoryBuffer) { + self.parent = parent + super.init(llvm: llvm, buffer: buffer) } - /// Returns a sequence of all the symbols in this object file. - public var symbols: SymbolSequence { - return SymbolSequence(llvm: LLVMGetSymbols(llvm), object: self) + private override init(llvm: LLVMBinaryRef, buffer: MemoryBuffer) { + fatalError() } - deinit { - LLVMDisposeObjectFile(llvm) + private override init(memoryBuffer: MemoryBuffer, in context: Context = .global) throws { + fatalError() } + } } /// A Section represents one of the binary sections in an object file. public struct Section { - /// The section's declared name. - public let name: String - /// The size of the contents of the section. - public let size: Int - /// The raw contents of the section. - public let contents: String - /// The address of the section in the object file. - public let address: Int - - /// The parent sequence of this section. - private let sectionIterator: LLVMSectionIteratorRef - - - internal init(fromIterator si: LLVMSectionIteratorRef) { - self.sectionIterator = si - self.name = String(cString: LLVMGetSectionName(si)) - self.size = Int(LLVMGetSectionSize(si)) - self.contents = String(cString: LLVMGetSectionContents(si)) - self.address = Int(LLVMGetSectionAddress(si)) - } + /// The section's declared name. + public let name: String + /// The size of the contents of the section. + public let size: Int + /// The raw contents of the section. + public let contents: UnsafeBufferPointer + /// The address of the section in the object file. + public let address: Int - /// Returns a sequence of all the relocations in this object file. - public var relocations: RelocationSequence { - return RelocationSequence( - llvm: LLVMGetRelocations(self.sectionIterator), - sectionIterator: self.sectionIterator - ) - } + /// The parent sequence of this section. + private let sectionIterator: LLVMSectionIteratorRef + + internal init(fromIterator si: LLVMSectionIteratorRef) { + self.sectionIterator = si + self.name = String(cString: LLVMGetSectionName(si)) + self.size = Int(LLVMGetSectionSize(si)) + self.contents = UnsafeBufferPointer(start: LLVMGetSectionContents(si), count: self.size) + self.address = Int(LLVMGetSectionAddress(si)) + } + + /// Returns a sequence of all the relocations in this object file. + public var relocations: RelocationSequence { + return RelocationSequence( + llvm: LLVMGetRelocations(self.sectionIterator), + sectionIterator: self.sectionIterator + ) + } + + /// Returns whether a symbol matching the given `Symbol` can be found in + /// this section. + public func contains(symbol: Symbol) -> Bool { + return LLVMGetSectionContainsSymbol(self.sectionIterator, symbol.symbolIterator) != 0 + } } /// A sequence for iterating over the sections in an object file. public class SectionSequence: Sequence { - let llvm: LLVMSectionIteratorRef - let objectFile: ObjectFile + let llvm: LLVMSectionIteratorRef? + let objectFile: ObjectFile - init(llvm: LLVMSectionIteratorRef, object: ObjectFile) { - self.llvm = llvm - self.objectFile = object - } + init(llvm: LLVMSectionIteratorRef?, object: ObjectFile) { + self.llvm = llvm + self.objectFile = object + } - /// Makes an iterator that iterates over the sections in an object file. - public func makeIterator() -> AnyIterator
{ - return AnyIterator { - if LLVMIsSectionIteratorAtEnd(self.objectFile.llvm, self.llvm) != 0 { - return nil - } - defer { LLVMMoveToNextSection(self.llvm) } - return Section(fromIterator: self.llvm) - } - } + /// Makes an iterator that iterates over the sections in an object file. + public func makeIterator() -> AnyIterator
{ + return AnyIterator { + guard let it = self.llvm else { + return nil + } - deinit { - LLVMDisposeSectionIterator(llvm) + if LLVMObjectFileIsSectionIteratorAtEnd(self.objectFile.llvm, it) != 0 { + return nil + } + defer { LLVMMoveToNextSection(it) } + return Section(fromIterator: it) } + } + + /// Deinitialize this value and dispose of its resources. + deinit { + LLVMDisposeSectionIterator(llvm) + } } /// A symbol is a top-level addressable entity in an object file. public struct Symbol { - /// The symbol name. - public let name: String - /// The size of the data in the symbol. - public let size: Int - /// The address of the symbol in the object file. - public let address: Int - - internal init(fromIterator si: LLVMSymbolIteratorRef) { - self.name = String(cString: LLVMGetSymbolName(si)) - self.size = Int(LLVMGetSymbolSize(si)) - self.address = Int(LLVMGetSymbolAddress(si)) - } + /// The symbol name. + public let name: String + /// The size of the data in the symbol. + public let size: Int + /// The address of the symbol in the object file. + public let address: Int + + /// The parent sequence of this symbol. + fileprivate let symbolIterator: LLVMSymbolIteratorRef + + internal init(fromIterator si: LLVMSymbolIteratorRef) { + self.name = String(cString: LLVMGetSymbolName(si)) + self.size = Int(LLVMGetSymbolSize(si)) + self.address = Int(LLVMGetSymbolAddress(si)) + self.symbolIterator = si + } } /// A Relocation represents the contents of a relocated symbol in the dynamic /// linker. public struct Relocation { - /// Retrieves the type of this relocation. - /// - /// The value of this integer is dependent upon the type of object file - /// it was retrieved from. - public let type: Int - /// The offset the relocated symbol resides at. - public let offset: Int - /// The symbol that is the subject of the relocation. - public let symbol: Symbol - /// Get a string that represents the type of this relocation for display - /// purposes. - public let typeName: String - - internal init(fromIterator ri: LLVMRelocationIteratorRef) { - self.type = Int(LLVMGetRelocationType(ri)) - self.offset = Int(LLVMGetRelocationOffset(ri)) - self.symbol = Symbol(fromIterator: LLVMGetRelocationSymbol(ri)) - self.typeName = String(cString: LLVMGetRelocationTypeName(ri)) - } + /// Retrieves the type of this relocation. + /// + /// The value of this integer is dependent upon the type of object file + /// it was retrieved from. + public let type: Int + /// The offset the relocated symbol resides at. + public let offset: Int + /// The symbol that is the subject of the relocation. + public let symbol: Symbol + /// Get a string that represents the type of this relocation for display + /// purposes. + public let typeName: String + + internal init(fromIterator ri: LLVMRelocationIteratorRef) { + self.type = Int(LLVMGetRelocationType(ri)) + self.offset = Int(LLVMGetRelocationOffset(ri)) + self.symbol = Symbol(fromIterator: LLVMGetRelocationSymbol(ri)) + self.typeName = String(cString: LLVMGetRelocationTypeName(ri)) + } } /// A sequence for iterating over the relocations in an object file. public class RelocationSequence: Sequence { - let llvm: LLVMRelocationIteratorRef - let sectionIterator: LLVMSectionIteratorRef + let llvm: LLVMRelocationIteratorRef + let sectionIterator: LLVMSectionIteratorRef - init(llvm: LLVMRelocationIteratorRef, sectionIterator: LLVMSectionIteratorRef) { - self.llvm = llvm - self.sectionIterator = sectionIterator - } + init(llvm: LLVMRelocationIteratorRef, sectionIterator: LLVMSectionIteratorRef) { + self.llvm = llvm + self.sectionIterator = sectionIterator + } - /// Creates an iterator that will iterate over all relocations in an object - /// file. - public func makeIterator() -> AnyIterator { - return AnyIterator { - if LLVMIsRelocationIteratorAtEnd(self.sectionIterator, self.llvm) != 0 { - return nil - } - defer { LLVMMoveToNextRelocation(self.llvm) } - return Relocation(fromIterator: self.llvm) - } + /// Creates an iterator that will iterate over all relocations in an object + /// file. + public func makeIterator() -> AnyIterator { + return AnyIterator { + if LLVMIsRelocationIteratorAtEnd(self.sectionIterator, self.llvm) != 0 { + return nil + } + defer { LLVMMoveToNextRelocation(self.llvm) } + return Relocation(fromIterator: self.llvm) } + } - deinit { - LLVMDisposeSectionIterator(llvm) - } + /// Deinitialize this value and dispose of its resources. + deinit { + LLVMDisposeSectionIterator(llvm) + } } /// A sequence for iterating over the symbols in an object file. public class SymbolSequence: Sequence { - let llvm: LLVMSymbolIteratorRef - let object: ObjectFile + let llvm: LLVMSymbolIteratorRef? + let object: ObjectFile - init(llvm: LLVMSymbolIteratorRef, object: ObjectFile) { - self.llvm = llvm - self.object = object - } + init(llvm: LLVMSymbolIteratorRef?, object: ObjectFile) { + self.llvm = llvm + self.object = object + } - /// Creates an iterator that will iterate over all symbols in an object - /// file. - public func makeIterator() -> AnyIterator { - return AnyIterator { - if LLVMIsSymbolIteratorAtEnd(self.object.llvm, self.llvm) != 0 { - return nil - } - defer { LLVMMoveToNextSymbol(self.llvm) } - return Symbol(fromIterator: self.llvm) - } + /// Creates an iterator that will iterate over all symbols in an object + /// file. + public func makeIterator() -> AnyIterator { + return AnyIterator { + guard let it = self.llvm else { + return nil + } + if LLVMObjectFileIsSymbolIteratorAtEnd(self.object.llvm, it) != 0 { + return nil + } + defer { LLVMMoveToNextSymbol(it) } + return Symbol(fromIterator: it) } - + } - - deinit { - LLVMDisposeSymbolIterator(llvm) - } + /// Deinitialize this value and dispose of its resources. + deinit { + LLVMDisposeSymbolIterator(llvm) + } } diff --git a/Sources/LLVM/OpCode.swift b/Sources/LLVM/OpCode.swift index 7c03c296..9aadf018 100644 --- a/Sources/LLVM/OpCode.swift +++ b/Sources/LLVM/OpCode.swift @@ -3,7 +3,7 @@ import cllvm #endif /// Enumerates the opcodes of instructions available in the LLVM IR language. -public enum OpCode { +public enum OpCode: CaseIterable { // MARK: Terminator Instructions /// The opcode for the `ret` instruction. @@ -230,7 +230,7 @@ public enum OpCode { extension OpCode { /// `BinaryOperation` enumerates the subset of opcodes that are binary operations. - public enum Binary { + public enum Binary: CaseIterable { /// The `add` instruction. case add /// The `fadd` instruction. @@ -281,10 +281,15 @@ extension OpCode { public var llvm: LLVMOpcode { return Binary.binaryOperationMap[self]! } + + /// Retrieves the corresponding opcode for this binary operation. + public var opCode: OpCode { + return OpCode(rawValue: self.llvm) + } } /// `CastOperation` enumerates the subset of opcodes that are cast operations. - public enum Cast { + public enum Cast: CaseIterable { /// The `trunc` instruction. case trunc /// The `zext` instruction. @@ -332,5 +337,10 @@ extension OpCode { public var llvm: LLVMOpcode { return Cast.castOperationMap[self]! } + + /// Retrieves the corresponding opcode for this cast operation. + public var opCode: OpCode { + return OpCode(rawValue: self.llvm) + } } } diff --git a/Sources/LLVM/Operation.swift b/Sources/LLVM/Operation.swift new file mode 100644 index 00000000..724b909c --- /dev/null +++ b/Sources/LLVM/Operation.swift @@ -0,0 +1,342 @@ +#if SWIFT_PACKAGE +import cllvm +#endif + +/// Species the behavior that should occur on overflow during mathematical +/// operations. +public enum OverflowBehavior { + /// The result value of the operator is the mathematical result modulo `2^n`, + /// where `n` is the bit width of the result. + case `default` + /// The result value of the operator is a poison value if signed overflow + /// occurs. + case noSignedWrap + /// The result value of the operator is a poison value if unsigned overflow + /// occurs. + case noUnsignedWrap +} + +/// The condition codes available for integer comparison instructions. +public enum IntPredicate { + /// Yields `true` if the operands are equal, false otherwise without sign + /// interpretation. + case equal + /// Yields `true` if the operands are unequal, false otherwise without sign + /// interpretation. + case notEqual + + /// Interprets the operands as unsigned values and yields true if the first is + /// greater than the second. + case unsignedGreaterThan + /// Interprets the operands as unsigned values and yields true if the first is + /// greater than or equal to the second. + case unsignedGreaterThanOrEqual + /// Interprets the operands as unsigned values and yields true if the first is + /// less than the second. + case unsignedLessThan + /// Interprets the operands as unsigned values and yields true if the first is + /// less than or equal to the second. + case unsignedLessThanOrEqual + + /// Interprets the operands as signed values and yields true if the first is + /// greater than the second. + case signedGreaterThan + /// Interprets the operands as signed values and yields true if the first is + /// greater than or equal to the second. + case signedGreaterThanOrEqual + /// Interprets the operands as signed values and yields true if the first is + /// less than the second. + case signedLessThan + /// Interprets the operands as signed values and yields true if the first is + /// less than or equal to the second. + case signedLessThanOrEqual + + private static let predicateMapping: [IntPredicate: LLVMIntPredicate] = [ + .equal: LLVMIntEQ, .notEqual: LLVMIntNE, .unsignedGreaterThan: LLVMIntUGT, + .unsignedGreaterThanOrEqual: LLVMIntUGE, .unsignedLessThan: LLVMIntULT, + .unsignedLessThanOrEqual: LLVMIntULE, .signedGreaterThan: LLVMIntSGT, + .signedGreaterThanOrEqual: LLVMIntSGE, .signedLessThan: LLVMIntSLT, + .signedLessThanOrEqual: LLVMIntSLE, + ] + + /// Retrieves the corresponding `LLVMIntPredicate`. + var llvm: LLVMIntPredicate { + return IntPredicate.predicateMapping[self]! + } +} + +/// The condition codes available for floating comparison instructions. +public enum RealPredicate { + /// No comparison, always returns `false`. + case `false` + /// Ordered and equal. + case orderedEqual + /// Ordered greater than. + case orderedGreaterThan + /// Ordered greater than or equal. + case orderedGreaterThanOrEqual + /// Ordered less than. + case orderedLessThan + /// Ordered less than or equal. + case orderedLessThanOrEqual + /// Ordered and not equal. + case orderedNotEqual + /// Ordered (no nans). + case ordered + /// Unordered (either nans). + case unordered + /// Unordered or equal. + case unorderedEqual + /// Unordered or greater than. + case unorderedGreaterThan + /// Unordered or greater than or equal. + case unorderedGreaterThanOrEqual + /// Unordered or less than. + case unorderedLessThan + /// Unordered or less than or equal. + case unorderedLessThanOrEqual + /// Unordered or not equal. + case unorderedNotEqual + /// No comparison, always returns `true`. + case `true` + + private static let predicateMapping: [RealPredicate: LLVMRealPredicate] = [ + .false: LLVMRealPredicateFalse, .orderedEqual: LLVMRealOEQ, + .orderedGreaterThan: LLVMRealOGT, .orderedGreaterThanOrEqual: LLVMRealOGE, + .orderedLessThan: LLVMRealOLT, .orderedLessThanOrEqual: LLVMRealOLE, + .orderedNotEqual: LLVMRealONE, .ordered: LLVMRealORD, .unordered: LLVMRealUNO, + .unorderedEqual: LLVMRealUEQ, .unorderedGreaterThan: LLVMRealUGT, + .unorderedGreaterThanOrEqual: LLVMRealUGE, .unorderedLessThan: LLVMRealULT, + .unorderedLessThanOrEqual: LLVMRealULE, .unorderedNotEqual: LLVMRealUNE, + .true: LLVMRealPredicateTrue, + ] + + /// Retrieves the corresponding `LLVMRealPredicate`. + var llvm: LLVMRealPredicate { + return RealPredicate.predicateMapping[self]! + } +} + +/// `AtomicOrdering` enumerates available memory ordering semantics. +/// +/// Atomic instructions (`cmpxchg`, `atomicrmw`, `fence`, `atomic load`, and +/// `atomic store`) take ordering parameters that determine which other atomic +/// instructions on the same address they synchronize with. These semantics are +/// borrowed from Java and C++0x, but are somewhat more colloquial. If these +/// descriptions aren’t precise enough, check those specs (see spec references +/// in the atomics guide). fence instructions treat these orderings somewhat +/// differently since they don’t take an address. See that instruction’s +/// documentation for details. +public enum AtomicOrdering: Comparable { + /// A load or store which is not atomic + case notAtomic + /// Lowest level of atomicity, guarantees somewhat sane results, lock free. + /// + /// The set of values that can be read is governed by the happens-before + /// partial order. A value cannot be read unless some operation wrote it. This + /// is intended to provide a guarantee strong enough to model Java’s + /// non-volatile shared variables. This ordering cannot be specified for + /// read-modify-write operations; it is not strong enough to make them atomic + /// in any interesting way. + case unordered + /// Guarantees that if you take all the operations affecting a specific + /// address, a consistent ordering exists. + /// + /// In addition to the guarantees of unordered, there is a single total order + /// for modifications by monotonic operations on each address. All + /// modification orders must be compatible with the happens-before order. + /// There is no guarantee that the modification orders can be combined to a + /// global total order for the whole program (and this often will not be + /// possible). The read in an atomic read-modify-write operation (cmpxchg and + /// atomicrmw) reads the value in the modification order immediately before + /// the value it writes. If one atomic read happens before another atomic read + /// of the same address, the later read must see the same value or a later + /// value in the address’s modification order. This disallows reordering of + /// monotonic (or stronger) operations on the same address. If an address is + /// written monotonic-ally by one thread, and other threads monotonic-ally + /// read that address repeatedly, the other threads must eventually see the + /// write. This corresponds to the C++0x/C1x memory_order_relaxed. + case monotonic + /// Acquire provides a barrier of the sort necessary to acquire a lock to + /// access other memory with normal loads and stores. + /// + /// In addition to the guarantees of monotonic, a synchronizes-with edge may + /// be formed with a release operation. This is intended to model C++’s + /// `memory_order_acquire`. + case acquire + /// Release is similar to Acquire, but with a barrier of the sort necessary to + /// release a lock. + /// + /// In addition to the guarantees of monotonic, if this operation writes a + /// value which is subsequently read by an acquire operation, it + /// synchronizes-with that operation. (This isn’t a complete description; see + /// the C++0x definition of a release sequence.) This corresponds to the + /// C++0x/C1x memory_order_release. + case release + /// provides both an Acquire and a Release barrier (for fences and operations + /// which both read and write memory). + /// + /// This corresponds to the C++0x/C1x memory_order_acq_rel. + case acquireRelease + /// Provides Acquire semantics for loads and Release semantics for stores. + /// + /// In addition to the guarantees of acq_rel (acquire for an operation that + /// only reads, release for an operation that only writes), there is a global + /// total order on all sequentially-consistent operations on all addresses, + /// which is consistent with the happens-before partial order and with the + /// modification orders of all the affected addresses. Each + /// sequentially-consistent read sees the last preceding write to the same + /// address in this global order. This corresponds to the C++0x/C1x + /// `memory_order_seq_cst` and Java volatile. + case sequentiallyConsistent + + private static let orderingMapping: [AtomicOrdering: LLVMAtomicOrdering] = [ + .notAtomic: LLVMAtomicOrderingNotAtomic, + .unordered: LLVMAtomicOrderingUnordered, + .monotonic: LLVMAtomicOrderingMonotonic, + .acquire: LLVMAtomicOrderingAcquire, + .release: LLVMAtomicOrderingRelease, + .acquireRelease: LLVMAtomicOrderingAcquireRelease, + .sequentiallyConsistent: LLVMAtomicOrderingSequentiallyConsistent, + ] + + /// Returns whether the left atomic ordering is strictly weaker than the + /// right atomic order. + public static func <(lhs: AtomicOrdering, rhs: AtomicOrdering) -> Bool { + return lhs.llvm.rawValue < rhs.llvm.rawValue + } + + /// Retrieves the corresponding `LLVMAtomicOrdering`. + var llvm: LLVMAtomicOrdering { + return AtomicOrdering.orderingMapping[self]! + } +} + +/// `AtomicReadModifyWriteOperation` enumerates the kinds of supported atomic +/// read-write-modify operations. +public enum AtomicReadModifyWriteOperation { + /// Set the new value and return the one old + /// + /// ``` + /// *ptr = val + /// ``` + case xchg + /// Add a value and return the old one + /// + /// ``` + /// *ptr = *ptr + val + /// ``` + case add + /// Subtract a value and return the old one + /// + /// ``` + /// *ptr = *ptr - val + /// ``` + case sub + /// And a value and return the old one + /// + /// ``` + /// *ptr = *ptr & val + /// ``` + case and + /// Not-And a value and return the old one + /// + /// ``` + /// *ptr = ~(*ptr & val) + /// ``` + case nand + /// OR a value and return the old one + /// + /// ``` + /// *ptr = *ptr | val + /// ``` + case or + /// Xor a value and return the old one + /// + /// ``` + /// *ptr = *ptr ^ val + /// ``` + case xor + /// Sets the value if it's greater than the original using a signed comparison + /// and return the old one. + /// + /// ``` + /// // Using a signed comparison + /// *ptr = *ptr > val ? *ptr : val + /// ``` + case max + /// Sets the value if it's Smaller than the original using a signed comparison + /// and return the old one. + /// + /// ``` + /// // Using a signed comparison + /// *ptr = *ptr < val ? *ptr : val + /// ``` + case min + /// Sets the value if it's greater than the original using an unsigned + /// comparison and return the old one. + /// + /// ``` + /// // Using an unsigned comparison + /// *ptr = *ptr > val ? *ptr : val + /// ``` + case umax + /// Sets the value if it's greater than the original using an unsigned + /// comparison and return the old one. + /// + /// ``` + /// // Using an unsigned comparison + /// *ptr = *ptr < val ? *ptr : val + /// ``` + case umin + + private static let atomicRMWMapping: [AtomicReadModifyWriteOperation: LLVMAtomicRMWBinOp] = [ + .xchg: LLVMAtomicRMWBinOpXchg, .add: LLVMAtomicRMWBinOpAdd, + .sub: LLVMAtomicRMWBinOpSub, .and: LLVMAtomicRMWBinOpAnd, + .nand: LLVMAtomicRMWBinOpNand, .or: LLVMAtomicRMWBinOpOr, + .xor: LLVMAtomicRMWBinOpXor, .max: LLVMAtomicRMWBinOpMax, + .min: LLVMAtomicRMWBinOpMin, .umax: LLVMAtomicRMWBinOpUMax, + .umin: LLVMAtomicRMWBinOpUMin, + ] + + /// Retrieves the corresponding `LLVMAtomicRMWBinOp`. + var llvm: LLVMAtomicRMWBinOp { + return AtomicReadModifyWriteOperation.atomicRMWMapping[self]! + } +} + +/// Enumerates the dialects of inline assembly LLVM's parsers can handle. +public enum InlineAssemblyDialect { + /// The dialect of assembly created at Bell Labs by AT&T. + /// + /// AT&T syntax differs from Intel syntax in a number of ways. Notably: + /// + /// - The source operand is before the destination operand + /// - Immediate operands are prefixed by a dollar-sign (`$`) + /// - Register operands are preceded by a percent-sign (`%`) + /// - The size of memory operands is determined from the last character of the + /// the opcode name. Valid suffixes include `b` for "byte" (8-bit), + /// `w` for "word" (16-bit), `l` for "long-word" (32-bit), and `q` for + /// "quad-word" (64-bit) memory references + case att + /// The dialect of assembly created at Intel. + /// + /// Intel syntax differs from AT&T syntax in a number of ways. Notably: + /// + /// - The destination operand is before the source operand + /// - Immediate and register operands have no prefix. + /// - Memory operands are annotated with their sizes. Valid annotations + /// include `byte ptr` (8-bit), `word ptr` (16-bit), `dword ptr` (32-bit) and + /// `qword ptr` (64-bit). + case intel + + private static let dialectMapping: [InlineAssemblyDialect: LLVMInlineAsmDialect] = [ + .att: LLVMInlineAsmDialectATT, + .intel: LLVMInlineAsmDialectIntel, + ] + + /// Retrieves the corresponding `LLVMInlineAsmDialect`. + var llvm: LLVMInlineAsmDialect { + return InlineAssemblyDialect.dialectMapping[self]! + } +} diff --git a/Sources/LLVM/PassManager.swift b/Sources/LLVM/PassManager.swift index 591d013b..be4c9dd6 100644 --- a/Sources/LLVM/PassManager.swift +++ b/Sources/LLVM/PassManager.swift @@ -3,7 +3,7 @@ import cllvm #endif /// A subset of supported LLVM IR optimizer passes. -public enum FunctionPass { +public enum Pass { /// This pass uses the SSA based Aggressive DCE algorithm. This algorithm /// assumes instructions are dead until proven otherwise, which makes /// it more successful are removing non-obviously dead instructions. @@ -44,6 +44,20 @@ public enum FunctionPass { /// %Z = add int 2, %X /// ``` case instructionCombining + /// Working in conjunction with the linker, iterate through all functions and + /// global values in the module and attempt to change their linkage from + /// external to internal. + /// + /// To preserve the linkage of a global value, return `true` from the given + /// callback. + case internalize(mustPreserve: (IRGlobal) -> Bool) + /// Working in conjunction with the linker, iterate through all functions and + /// global values in the module and attempt to change their linkage from + /// external to internal. + /// + /// When a function with the name "main" is encountered, if the value of + /// `preserveMain` is `true`, "main" will not be internalized. + case internalizeAll(preserveMain: Bool) /// Thread control through mult-pred/multi-succ blocks where some preds /// always go to some succ. Thresholds other than minus one override the /// internal BB duplication default threshold. @@ -60,8 +74,13 @@ public enum FunctionPass { case loopReroll /// This pass is a simple loop unrolling pass. case loopUnroll + /// This pass is a simple loop unroll-and-jam pass. + case loopUnrollAndJam /// This pass is a simple loop unswitching pass. case loopUnswitch + /// This pass lowers atomic intrinsics to non-atomic form for use in a known + /// non-preemptible environment. + case lowerAtomic /// This pass performs optimizations related to eliminating `memcpy` calls /// and/or combining multiple stores into memset's. case memCpyOpt @@ -70,7 +89,7 @@ public enum FunctionPass { /// This pass converts SwitchInst instructions into a sequence of chained /// binary branch instructions. case lowerSwitch - /// This pass is used to promote memory references to + /// This pass is used to promote memory references to /// be register references. A simple example of the transformation performed /// by this pass is going from code like this: /// @@ -87,6 +106,10 @@ public enum FunctionPass { /// ret i32 42 /// ``` case promoteMemoryToRegister + /// Adds DWARF discriminators to the IR. Discriminators are + /// used to decide what CFG path was taken inside sub-graphs whose instructions + /// share the same line and column number information. + case addDiscriminators /// This pass reassociates commutative expressions in an order that /// is designed to promote better constant propagation, GCSE, LICM, PRE, etc. /// @@ -97,12 +120,6 @@ public enum FunctionPass { case reassociate /// Sparse conditional constant propagation. case sccp - /// Replace aggregates or pieces of aggregates with scalar SSA values. - case scalarReplAggregates - /// Replace aggregates or pieces of aggregates with scalar SSA values. - case scalarReplAggregatesSSA - /// Tries to inline the fast path of library calls such as sqrt. - case simplifyLibCalls /// This pass eliminates call instructions to the current function which occur /// immediately before return instructions. case tailCallElimination @@ -117,13 +134,47 @@ public enum FunctionPass { case earlyCSE /// Removes `llvm.expect` intrinsics and creates "block_weights" metadata. case lowerExpectIntrinsic - /// Adds metadata to LLVM IR types and performs metadata-based TBAA. + /// Adds metadata to LLVM IR types and performs metadata-based + /// Type-Based Alias Analysis (TBAA). + /// + /// TBAA requires that two pointers to objects of different types must never + /// alias. Because memory in LLVM is typeless, TBAA is performed using + /// special metadata nodes describing aliasing relationships between types + /// in the source language(s). + /// + /// To construct this metadata, see `MDBuilder`. case typeBasedAliasAnalysis /// Adds metadata to LLVM IR types and performs metadata-based scoped no-alias /// analysis. case scopedNoAliasAA /// LLVM's primary stateless and local alias analysis. + /// + /// Given a pointer value, walk the use-def chain to find out how that + /// pointer is used. The traversal terminates at global variables and + /// aliases, stack allocations, and values of non-pointer types - referred + /// to as "underlying objects". Analysis may reach multiple underlying object + /// values because of branching control flow. If the set of underlying + /// objects for one pointer has a non-empty intersection with another, those + /// two pointers are deemed `mayalias`. Else, an empty intersection deems + /// those pointers `noalias`. + /// + /// Basic Alias Analysis should generally be scheduled ahead of other + /// AA passes. This is because it is more conservative than other passes + /// about declaring two pointers `mustalias`, and does so fairly efficiently. + /// For example, loads through two members of a union with distinct types are + /// declared by TBAA to be `noalias`, where BasicAA considers them + /// `mustalias`. case basicAliasAnalysis + /// Performs alias and mod/ref analysis for internal global values that + /// do not have their address taken. + /// + /// Internal global variables that are only loaded from may be marked as + /// constants. + case globalsAliasAnalysis + /// This pass is used to ensure that functions have at most one return + /// instruction in them. Additionally, it keeps track of which node is + /// the new exit node of the CFG. + case unifyFunctionExitNodes /// Runs the LLVM IR Verifier to sanity check the results of passes. case verifier /// A pass to inline and remove functions marked as "always_inline". @@ -161,6 +212,9 @@ public enum FunctionPass { /// Return a new pass object which transforms invoke instructions into calls, /// if the callee can *not* unwind the stack. case pruneEH + /// This transformation attempts to discovery `alloca` allocations of aggregates that can be + /// broken down into component scalar values. + case scalarReplacementOfAggregates /// This pass removes any function declarations (prototypes) that are not used. case stripDeadPrototypes /// These functions removes symbols from functions and modules without @@ -172,70 +226,26 @@ public enum FunctionPass { /// This pass performs a superword-level parallelism pass to combine /// similar independent instructions into vector instructions. case slpVectorize + /// An invalid pass that crashes when added to the pass manager. + case invalid(reason: String) +} + +extension Pass { + @available(*, deprecated, message: "Pass has been removed") + static let simplifyLibCalls: Pass = .invalid(reason: "Pass has been removed") + @available(*, deprecated, message: "Use the scalarReplacementOfAggregates instead") + static let scalarReplAggregates: Pass = .invalid(reason: "Pass has been renamed to 'scalarReplacementOfAggregates'") + @available(*, deprecated, message: "Use the scalarReplacementOfAggregates instead") + static let scalarReplAggregatesSSA: Pass = .invalid(reason: "Pass has been renamed to 'scalarReplacementOfAggregates'") } /// A `FunctionPassManager` is an object that collects a sequence of passes /// which run over a particular IR construct, and runs each of them in sequence /// over each such construct. +@available(*, deprecated, message: "Use the PassPipeliner instead") public class FunctionPassManager { internal let llvm: LLVMPassManagerRef - - private static let passMapping: [FunctionPass: (LLVMPassManagerRef) -> Void] = [ - .aggressiveDCE: LLVMAddAggressiveDCEPass, - .bitTrackingDCE: LLVMAddBitTrackingDCEPass, - .alignmentFromAssumptions: LLVMAddAlignmentFromAssumptionsPass, - .cfgSimplification: LLVMAddCFGSimplificationPass, - .deadStoreElimination: LLVMAddDeadStoreEliminationPass, - .scalarizer: LLVMAddScalarizerPass, - .mergedLoadStoreMotion: LLVMAddMergedLoadStoreMotionPass, - .gvn: LLVMAddGVNPass, - .indVarSimplify: LLVMAddIndVarSimplifyPass, - .instructionCombining: LLVMAddInstructionCombiningPass, - .jumpThreading: LLVMAddJumpThreadingPass, - .licm: LLVMAddLICMPass, - .loopDeletion: LLVMAddLoopDeletionPass, - .loopIdiom: LLVMAddLoopIdiomPass, - .loopRotate: LLVMAddLoopRotatePass, - .loopReroll: LLVMAddLoopRerollPass, - .loopUnroll: LLVMAddLoopUnrollPass, - .loopUnswitch: LLVMAddLoopUnswitchPass, - .memCpyOpt: LLVMAddMemCpyOptPass, - .partiallyInlineLibCalls: LLVMAddPartiallyInlineLibCallsPass, - .lowerSwitch: LLVMAddLowerSwitchPass, - .promoteMemoryToRegister: LLVMAddPromoteMemoryToRegisterPass, - .reassociate: LLVMAddReassociatePass, - .sccp: LLVMAddSCCPPass, - .scalarReplAggregates: LLVMAddScalarReplAggregatesPass, - .scalarReplAggregatesSSA: LLVMAddScalarReplAggregatesPassSSA, - .simplifyLibCalls: LLVMAddSimplifyLibCallsPass, - .tailCallElimination: LLVMAddTailCallEliminationPass, - .constantPropagation: LLVMAddConstantPropagationPass, - .demoteMemoryToRegister: LLVMAddDemoteMemoryToRegisterPass, - .verifier: LLVMAddVerifierPass, - .correlatedValuePropagation: LLVMAddCorrelatedValuePropagationPass, - .earlyCSE: LLVMAddEarlyCSEPass, - .lowerExpectIntrinsic: LLVMAddLowerExpectIntrinsicPass, - .typeBasedAliasAnalysis: LLVMAddTypeBasedAliasAnalysisPass, - .scopedNoAliasAA: LLVMAddScopedNoAliasAAPass, - .basicAliasAnalysis: LLVMAddBasicAliasAnalysisPass, - .alwaysInliner: LLVMAddAlwaysInlinerPass, - .argumentPromotion: LLVMAddArgumentPromotionPass, - .constantMerge: LLVMAddConstantMergePass, - .deadArgElimination: LLVMAddDeadArgEliminationPass, - .functionAttrs: LLVMAddFunctionAttrsPass, - .functionInlining: LLVMAddFunctionInliningPass, - .globalDCE: LLVMAddGlobalDCEPass, - .globalOptimizer: LLVMAddGlobalOptimizerPass, - .ipConstantPropagation: LLVMAddIPConstantPropagationPass, - .ipscc: LLVMAddIPSCCPPass, - .pruneEH: LLVMAddPruneEHPass, - .stripDeadPrototypes: LLVMAddStripDeadPrototypesPass, - .stripSymbols: LLVMAddStripSymbolsPass, - .loopVectorize: LLVMAddLoopVectorizePass, - .slpVectorize: LLVMAddSLPVectorizePass, - // .internalize: LLVMAddInternalizePass, - // .sroaWithThreshhold: LLVMAddScalarReplAggregatesPassWithThreshold, - ] + var alivePassObjects = [Any]() /// Creates a `FunctionPassManager` bound to the given module's IR. public init(module: Module) { @@ -247,9 +257,9 @@ public class FunctionPassManager { /// /// - parameter passes: A list of function passes to add to the pass manager's /// list of passes to run. - public func add(_ passes: FunctionPass...) { + public func add(_ passes: Pass...) { for pass in passes { - FunctionPassManager.passMapping[pass]!(llvm) + PassPipeliner.configurePass(pass, passManager: llvm, keepalive: &alivePassObjects) } } @@ -260,3 +270,8 @@ public class FunctionPassManager { LLVMRunFunctionPassManager(llvm, function.asLLVM()) } } + +/// A subset of supported LLVM IR optimizer passes. +@available(*, deprecated, renamed: "Pass") +public typealias FunctionPass = Pass + diff --git a/Sources/LLVM/PassPipeliner.swift b/Sources/LLVM/PassPipeliner.swift new file mode 100644 index 00000000..c4f6088e --- /dev/null +++ b/Sources/LLVM/PassPipeliner.swift @@ -0,0 +1,408 @@ +#if SWIFT_PACKAGE +import cllvm +import llvmshims +#endif + +/// Implements a pass manager, pipeliner, and executor for a set of +/// user-provided optimization passes. +/// +/// A `PassPipeliner` handles the creation of a related set of optimization +/// passes called a "pipeline". Grouping passes is done for multiple reasons, +/// chief among them is that optimizer passes are extremely sensitive to their +/// ordering relative to other passes. In addition, pass groupings allow for +/// the clean segregation of otherwise unrelated passes. For example, a +/// pipeline might consist of "mandatory" passes such as Jump Threading, LICM, +/// and DCE in one pipeline and "diagnostic" passes in another. +public final class PassPipeliner { + private enum PipelinePlan { + case builtinPasses([Pass]) + case functionPassManager(LLVMPassManagerRef) + case modulePassManager(LLVMPassManagerRef) + } + + /// The module for this pass pipeline. + public let module: Module + /// The pipeline stages registered with this pass pipeliner. + public private(set) var stages: [String] + + private var stageMapping: [String: PipelinePlan] + private var frozen: Bool = false + + /// A helper object that can add passes to a pipeline. + /// + /// To add a new pass, call `add(_:)`. + public final class Builder { + fileprivate var passes: [Pass] = [] + + fileprivate init() {} + + /// Appends a pass to the current pipeline. + public func add(_ type: Pass) { + self.passes.append(type) + } + } + + /// Initializes a new, empty pipeliner. + /// + /// - Parameter module: The module the pipeliner will run over. + public init(module: Module) { + self.module = module + self.stages = [] + self.stageMapping = [:] + } + + deinit { + for stage in stageMapping.values { + switch stage { + case let .functionPassManager(pm): + LLVMDisposePassManager(pm) + case let .modulePassManager(pm): + LLVMDisposePassManager(pm) + case .builtinPasses(_): + continue + } + } + } + + /// Appends a stage to the pipeliner. + /// + /// The staging function provides a `Builder` object into which the types + /// of passes for a given pipeline are inserted. + /// + /// - Parameters: + /// - name: The name of the pipeline stage. + /// - stager: A builder function. + public func addStage(_ name: String, _ stager: (Builder) -> Void) { + precondition(!self.frozen, "Cannot add new stages to a frozen pipeline!") + + self.frozen = true + defer { self.frozen = false } + + self.stages.append(name) + let builder = Builder() + stager(builder) + self.stageMapping[name] = .builtinPasses(builder.passes) + } + + /// Executes the entirety of the pass pipeline. + /// + /// Execution of passes is done in a loop that is divided into two phases. + /// The first phase aggregates all local passes and stops aggregation when + /// it encounters a module-level pass. This group of local passes + /// is then run one at a time on the same scope. The second phase is entered + /// and the module pass is run. The first phase is then re-entered until all + /// local passes have run on all local scopes and all intervening module + /// passes have been run. + /// + /// The same pipeline may be repeatedly re-executed, but pipeline execution + /// is not re-entrancy safe. + /// + /// - Parameter pipelineMask: Describes the subset of pipelines that should + /// be executed. If the mask is empty, all pipelines will be executed. + public func execute(mask pipelineMask: Set = []) { + precondition(!self.frozen, "Cannot execute a frozen pipeline!") + + self.frozen = true + defer { self.frozen = false } + + stageLoop: for stage in self.stages { + guard pipelineMask.isEmpty || pipelineMask.contains(stage) else { + continue + } + + guard let pipeline = self.stageMapping[stage] else { + fatalError("Unregistered pass stage?") + } + + switch pipeline { + case let .builtinPasses(passTypes): + guard !passTypes.isEmpty else { + continue stageLoop + } + self.runPasses(passTypes) + case let .functionPassManager(pm): + self.runFunctionPasses([], pm) + case let .modulePassManager(pm): + LLVMRunPassManager(pm, self.module.llvm) + } + } + } + + private func runFunctionPasses(_ passes: [Pass], _ pm: LLVMPassManagerRef) { + var keepalive = [Any]() + LLVMInitializeFunctionPassManager(pm) + + for pass in passes { + PassPipeliner.configurePass(pass, passManager: pm, keepalive: &keepalive) + } + + for function in self.module.functions { + LLVMRunFunctionPassManager(pm, function.asLLVM()) + } + } + + private func runPasses(_ passes: [Pass]) { + var keepalive = [Any]() + let pm = LLVMCreatePassManager()! + for pass in passes { + PassPipeliner.configurePass(pass, passManager: pm, keepalive: &keepalive) + } + LLVMRunPassManager(pm, self.module.llvm) + LLVMDisposePassManager(pm) + } +} + +// MARK: Standard Pass Pipelines + +extension PassPipeliner { + /// Adds a pipeline stage populated with function passes that LLVM considers + /// standard for languages like C and C++. Additional parameters are + /// available to tune the overall behavior of the optimization pipeline at a + /// macro level. + /// + /// - Parameters: + /// - name: The name of the pipeline stage. + /// - optimization: The level of optimization. + /// - size: The level of size optimization. + public func addStandardFunctionPipeline( + _ name: String, + optimization: CodeGenOptLevel = .`default`, + size: CodeGenOptLevel = .none + ) { + let passBuilder = self.configurePassBuilder(optimization, size) + let functionPasses = + LLVMCreateFunctionPassManagerForModule(self.module.llvm)! + LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder, + functionPasses) + LLVMPassManagerBuilderDispose(passBuilder) + self.stages.append(name) + self.stageMapping[name] = .functionPassManager(functionPasses) + } + + /// Adds a pipeline stage populated with module passes that LLVM considers + /// standard for languages like C and C++. Additional parameters are + /// available to tune the overall behavior of the optimization pipeline at a + /// macro level. + /// + /// - Parameters: + /// - name: The name of the pipeline stage. + /// - optimization: The level of optimization. + /// - size: The level of size optimization. + public func addStandardModulePipeline( + _ name: String, + optimization: CodeGenOptLevel = .`default`, + size: CodeGenOptLevel = .none + ) { + let passBuilder = self.configurePassBuilder(optimization, size) + let modulePasses = LLVMCreatePassManager()! + LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses) + LLVMPassManagerBuilderDispose(passBuilder) + self.stages.append(name) + self.stageMapping[name] = .modulePassManager(modulePasses) + } + + private func configurePassBuilder( + _ opt: CodeGenOptLevel, + _ size: CodeGenOptLevel + ) -> LLVMPassManagerBuilderRef { + let passBuilder = LLVMPassManagerBuilderCreate()! + switch opt { + case .none: + LLVMPassManagerBuilderSetOptLevel(passBuilder, 0) + case .less: + LLVMPassManagerBuilderSetOptLevel(passBuilder, 1) + case .default: + LLVMPassManagerBuilderSetOptLevel(passBuilder, 2) + case .aggressive: + LLVMPassManagerBuilderSetOptLevel(passBuilder, 3) + } + + switch size { + case .none: + LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0) + case .less: + LLVMPassManagerBuilderSetSizeLevel(passBuilder, 1) + case .default: + LLVMPassManagerBuilderSetSizeLevel(passBuilder, 2) + case .aggressive: + LLVMPassManagerBuilderSetSizeLevel(passBuilder, 3) + } + + return passBuilder + } +} + + +extension PassPipeliner { + /// Configures and adds a pass to the given pass manager. + /// + /// - Parameters: + /// - pass: The pass to add to the pass manager. + /// - passManager: The pass manager to which to add a pass. + /// - keepalive: An array that must stay alive for as long as this pass + /// manager stays alive. This array will keep Swift objects + /// that may be passed into closures that will use them at + /// any point in the pass execution line. + static func configurePass( + _ pass: Pass, + passManager: LLVMPassManagerRef, + keepalive: inout [Any]) { + switch pass { + case .invalid(let reason): + fatalError("Cannot configure pass: \(reason)") + case .aggressiveDCE: + LLVMAddAggressiveDCEPass(passManager) + case .bitTrackingDCE: + LLVMAddBitTrackingDCEPass(passManager) + case .alignmentFromAssumptions: + LLVMAddAlignmentFromAssumptionsPass(passManager) + case .cfgSimplification: + LLVMAddCFGSimplificationPass(passManager) + case .deadStoreElimination: + LLVMAddDeadStoreEliminationPass(passManager) + case .scalarizer: + LLVMAddScalarizerPass(passManager) + case .mergedLoadStoreMotion: + LLVMAddMergedLoadStoreMotionPass(passManager) + case .gvn: + LLVMAddGVNPass(passManager) + case .indVarSimplify: + LLVMAddIndVarSimplifyPass(passManager) + case .instructionCombining: + LLVMAddInstructionCombiningPass(passManager) + case .jumpThreading: + LLVMAddJumpThreadingPass(passManager) + case .licm: + LLVMAddLICMPass(passManager) + case .loopDeletion: + LLVMAddLoopDeletionPass(passManager) + case .loopIdiom: + LLVMAddLoopIdiomPass(passManager) + case .loopRotate: + LLVMAddLoopRotatePass(passManager) + case .loopReroll: + LLVMAddLoopRerollPass(passManager) + case .loopUnroll: + LLVMAddLoopUnrollPass(passManager) + case .loopUnrollAndJam: + LLVMAddLoopUnrollAndJamPass(passManager) + case .loopUnswitch: + LLVMAddLoopUnswitchPass(passManager) + case .lowerAtomic: + LLVMAddLowerAtomicPass(passManager) + case .memCpyOpt: + LLVMAddMemCpyOptPass(passManager) + case .partiallyInlineLibCalls: + LLVMAddPartiallyInlineLibCallsPass(passManager) + case .lowerSwitch: + LLVMAddLowerSwitchPass(passManager) + case .promoteMemoryToRegister: + LLVMAddPromoteMemoryToRegisterPass(passManager) + case .addDiscriminators: + LLVMAddAddDiscriminatorsPass(passManager) + case .reassociate: + LLVMAddReassociatePass(passManager) + case .sccp: + LLVMAddSCCPPass(passManager) + case .tailCallElimination: + LLVMAddTailCallEliminationPass(passManager) + case .constantPropagation: + LLVMAddConstantPropagationPass(passManager) + case .demoteMemoryToRegister: + LLVMAddDemoteMemoryToRegisterPass(passManager) + case .verifier: + LLVMAddVerifierPass(passManager) + case .correlatedValuePropagation: + LLVMAddCorrelatedValuePropagationPass(passManager) + case .earlyCSE: + LLVMAddEarlyCSEPass(passManager) + case .lowerExpectIntrinsic: + LLVMAddLowerExpectIntrinsicPass(passManager) + case .typeBasedAliasAnalysis: + LLVMAddTypeBasedAliasAnalysisPass(passManager) + case .scopedNoAliasAA: + LLVMAddScopedNoAliasAAPass(passManager) + case .basicAliasAnalysis: + LLVMAddBasicAliasAnalysisPass(passManager) + case .globalsAliasAnalysis: + LLVMAddGlobalsAAWrapperPass(passManager) + case .unifyFunctionExitNodes: + LLVMAddUnifyFunctionExitNodesPass(passManager) + case .alwaysInliner: + LLVMAddAlwaysInlinerPass(passManager) + case .argumentPromotion: + LLVMAddArgumentPromotionPass(passManager) + case .constantMerge: + LLVMAddConstantMergePass(passManager) + case .deadArgElimination: + LLVMAddDeadArgEliminationPass(passManager) + case .functionAttrs: + LLVMAddFunctionAttrsPass(passManager) + case .functionInlining: + LLVMAddFunctionInliningPass(passManager) + case .globalDCE: + LLVMAddGlobalDCEPass(passManager) + case .globalOptimizer: + LLVMAddGlobalOptimizerPass(passManager) + case .ipConstantPropagation: + LLVMAddIPConstantPropagationPass(passManager) + case .ipscc: + LLVMAddIPSCCPPass(passManager) + case .pruneEH: + LLVMAddPruneEHPass(passManager) + case .stripDeadPrototypes: + LLVMAddStripDeadPrototypesPass(passManager) + case .stripSymbols: + LLVMAddStripSymbolsPass(passManager) + case .loopVectorize: + LLVMAddLoopVectorizePass(passManager) + case .slpVectorize: + LLVMAddSLPVectorizePass(passManager) + case .internalizeAll(let preserveMain): + LLVMAddInternalizePass(passManager, preserveMain == false ? 0 : 1) + case .internalize(let pred): + // The lifetime of this callback is must be manually managed to ensure + // it remains alive across the execution of the given pass manager. + + // Create a callback context at +1 + let callbackContext = InternalizeCallbackContext(pred) + // Stick it in the keepalive array, now at +2 + keepalive.append(callbackContext) + // Pass it unmanaged at +2 + let contextPtr = Unmanaged.passUnretained(callbackContext).toOpaque() + LLVMAddInternalizePassWithMustPreservePredicate(passManager, contextPtr) { globalValue, callbackCtx in + guard let globalValue = globalValue, let callbackCtx = callbackCtx else { + fatalError("Global value and context must be non-nil") + } + + let callback = Unmanaged.fromOpaque(callbackCtx).takeUnretainedValue() + return callback.block(realizeGlobalValue(globalValue)).llvm + } + // Context dropped, now at +1 + // When the keepalive array is dropped by the caller, it will drop to +0. + case .scalarReplacementOfAggregates: + LLVMAddScalarReplAggregatesPassWithThreshold(passManager, /*ignored*/ 0) + } + } +} + +private func realizeGlobalValue(_ llvm: LLVMValueRef) -> IRGlobal { + precondition(llvm.isAGlobalValue, "must be a global value") + if llvm.isAFunction { + return Function(llvm: llvm) + } else if llvm.isAGlobalAlias { + return Alias(llvm: llvm) + } else if llvm.isAGlobalVariable { + return Global(llvm: llvm) + } else { + fatalError("unrecognized global value") + } +} + +private class InternalizeCallbackContext { + fileprivate let block: (IRGlobal) -> Bool + + fileprivate init(_ block: @escaping (IRGlobal) -> Bool) { + self.block = block + } +} diff --git a/Sources/LLVM/PhiNode.swift b/Sources/LLVM/PhiNode.swift index 06f46793..52c89291 100644 --- a/Sources/LLVM/PhiNode.swift +++ b/Sources/LLVM/PhiNode.swift @@ -32,7 +32,7 @@ import cllvm /// /// If the flow of control reaches `aCondTrue`, the value of `b` is `2`, else it /// is `1` and SSA semantics are preserved. -public struct PhiNode: IRValue { +public struct PhiNode: IRInstruction { internal let llvm: LLVMValueRef /// Adds a list of incoming value and their associated basic blocks to the end diff --git a/Sources/LLVM/PointerType.swift b/Sources/LLVM/PointerType.swift index 77c4a957..e3b036ad 100644 --- a/Sources/LLVM/PointerType.swift +++ b/Sources/LLVM/PointerType.swift @@ -16,7 +16,7 @@ public struct PointerType: IRType { /// Retrieves the type of the value being pointed to. public let pointee: IRType /// Retrieves the address space where the pointed-to object resides. - public let addressSpace: Int + public let addressSpace: AddressSpace /// Creates a `PointerType` from a pointee type and an optional address space. /// @@ -24,7 +24,7 @@ public struct PointerType: IRType { /// - parameter addressSpace: The optional address space where the pointed-to /// object resides. /// - note: The context of this type is taken from it's pointee - public init(pointee: IRType, addressSpace: Int = 0) { + public init(pointee: IRType, addressSpace: AddressSpace = .zero) { // FIXME: This class of invalid reference is not caught by Module.verify(), // only `lli`. if pointee is VoidType { @@ -40,6 +40,12 @@ public struct PointerType: IRType { /// Retrieves the underlying LLVM type object. public func asLLVM() -> LLVMTypeRef { - return LLVMPointerType(pointee.asLLVM(), UInt32(addressSpace)) + return LLVMPointerType(pointee.asLLVM(), UInt32(addressSpace.rawValue)) + } +} + +extension PointerType: Equatable { + public static func == (lhs: PointerType, rhs: PointerType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() } } diff --git a/Sources/LLVM/StructType.swift b/Sources/LLVM/StructType.swift index 609a3011..c71be697 100644 --- a/Sources/LLVM/StructType.swift +++ b/Sources/LLVM/StructType.swift @@ -115,4 +115,37 @@ public struct StructType: IRType { public func asLLVM() -> LLVMTypeRef { return llvm } + + /// Return true if this is a struct type with an identity that has an + /// unspecified body. + /// + /// Opaque struct types print as `opaque` in serialized .ll files. + public var isOpaque: Bool { + return LLVMIsOpaqueStruct(self.llvm) != 0 + } + + /// Returns true if this is a packed struct type. + /// + /// A packed struct type includes no padding between fields and is thus + /// laid out in one contiguous region of memory with its elements laid out + /// one after the other. A non-packed struct type includes padding according + /// to the data layout of the target. + public var isPacked: Bool { + return LLVMIsPackedStruct(self.llvm) != 0 + } + + /// Returns true if this is a literal struct type. + /// + /// A literal struct type is uniqued by structural equivalence - that is, + /// regardless of how it is named, two literal structures are equal if + /// their fields are equal. + public var isLiteral: Bool { + return LLVMIsLiteralStruct(self.llvm) != 0 + } +} + +extension StructType: Equatable { + public static func == (lhs: StructType, rhs: StructType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() + } } diff --git a/Sources/LLVM/Switch.swift b/Sources/LLVM/Switch.swift index b90b7ffe..fd09e1d2 100644 --- a/Sources/LLVM/Switch.swift +++ b/Sources/LLVM/Switch.swift @@ -6,7 +6,7 @@ import cllvm /// defines a jump table of values and destination basic blocks to pass the flow /// of control to if a condition value matches. If no match is made, control /// flow passes to the default basic block. -public struct Switch: IRValue { +public struct Switch: IRInstruction { internal let llvm: LLVMValueRef /// Inserts a case with the given value and destination basic block in the diff --git a/Sources/LLVM/TargetData.swift b/Sources/LLVM/TargetData.swift index b5a03030..d90eb2bc 100644 --- a/Sources/LLVM/TargetData.swift +++ b/Sources/LLVM/TargetData.swift @@ -7,6 +7,7 @@ import cllvm /// sizes and offsets of types with respect to this target. public class TargetData { internal let llvm: LLVMTargetDataRef + private var structLayoutCache = [LLVMTypeRef: StructLayout]() /// Creates a Target Data object from an `LLVMTargetDataRef` object. public init(llvm: LLVMTargetDataRef) { @@ -16,7 +17,7 @@ public class TargetData { /// Computes the byte offset of the indexed struct element for a target. /// /// - parameter element: The index of the element in the given structure to - // compute. + /// compute. /// - parameter type: The type of the structure to compute the offset with. /// /// - returns: The offset of the given element within the structure. @@ -46,16 +47,6 @@ public class TargetData { return Int(LLVMSizeOfTypeInBits(llvm, type.asLLVM())) } - /// Computes the minimum ABI-required number of bits necessary to hold a value - /// of the given type for this target environment. - /// - /// - parameter type: The type to compute the size of. - /// - /// - returns: The minimum ABI-required size of the type in bytes. - public func abiSizeOfType(_ type: IRType) -> Int { - return Int(LLVMABISizeOfType(llvm, type.asLLVM())) - } - /// The current platform byte order, either big or little endian. public var byteOrder: ByteOrder { return ByteOrder(llvm: LLVMByteOrder(llvm)) @@ -75,17 +66,9 @@ public class TargetData { /// - addressSpace: The address space in which to derive the type. /// - returns: An IntegerType that is the same size as the pointer type /// on this target. - public func intPointerType(context: Context? = nil, addressSpace: Int? = nil) -> IntType { - let type: LLVMTypeRef - switch (context, addressSpace) { - case let (context?, addressSpace?): - type = LLVMIntPtrTypeForASInContext(context.llvm, llvm, UInt32(addressSpace)) - case let (nil, addressSpace?): - type = LLVMIntPtrTypeForAS(llvm, UInt32(addressSpace)) - case let (context?, nil): - type = LLVMIntPtrTypeInContext(context.llvm, llvm) - case (nil, nil): - type = LLVMIntPtrType(llvm) + public func intPointerType(context: Context = .global, addressSpace: AddressSpace = .zero) -> IntType { + guard let type = LLVMIntPtrTypeForASInContext(context.llvm, llvm, UInt32(addressSpace.rawValue)) else { + fatalError() } return convertType(type) as! IntType // Guaranteed to succeed } @@ -94,24 +77,24 @@ public class TargetData { /// /// - parameter global: The global variable /// - returns: The variable's preferred alignment in this target - public func preferredAlignment(of global: Global) -> Int { - return Int(LLVMPreferredAlignmentOfGlobal(llvm, global.asLLVM())) + public func preferredAlignment(of global: Global) -> Alignment { + return Alignment(LLVMPreferredAlignmentOfGlobal(llvm, global.asLLVM())) } /// Computes the preferred alignment of the given type for this target /// /// - parameter type: The type for which you're computing the alignment /// - returns: The type's preferred alignment in this target - public func preferredAlignment(of type: IRType) -> Int { - return Int(LLVMPreferredAlignmentOfType(llvm, type.asLLVM())) + public func preferredAlignment(of type: IRType) -> Alignment { + return Alignment(LLVMPreferredAlignmentOfType(llvm, type.asLLVM())) } /// Computes the minimum ABI-required alignment for the specified type. /// /// - parameter type: The type to whose ABI alignment you wish to compute. /// - returns: The minimum ABI-required alignment for the specified type. - public func abiAlignment(of type: IRType) -> Int { - return Int(LLVMABIAlignmentOfType(llvm, type.asLLVM())) + public func abiAlignment(of type: IRType) -> Alignment { + return Alignment(LLVMABIAlignmentOfType(llvm, type.asLLVM())) } /// Computes the minimum ABI-required alignment for the specified type. @@ -120,24 +103,24 @@ public class TargetData { /// /// - parameter type: The type to whose ABI alignment you wish to compute. /// - returns: The minimum ABI-required alignment for the specified type. - public func callFrameAlignment(of type: IRType) -> Int { - return Int(LLVMCallFrameAlignmentOfType(llvm, type.asLLVM())) + public func callFrameAlignment(of type: IRType) -> Alignment { + return Alignment(LLVMCallFrameAlignmentOfType(llvm, type.asLLVM())) } /// Computes the ABI size of a type in bytes for a target. /// /// - parameter type: The type to whose ABI size you wish to compute. /// - returns: The ABI size for the specified type. - public func abiSize(of type: IRType) -> Int { - return Int(LLVMABISizeOfType(llvm, type.asLLVM())) + public func abiSize(of type: IRType) -> Size { + return Size(LLVMABISizeOfType(llvm, type.asLLVM())) } /// Computes the maximum number of bytes that may be overwritten by /// storing the specified type. /// /// - parameter type: The type to whose store size you wish to compute. /// - returns: The store size of the type in the given target. - public func storeSize(of type: IRType) -> Int { - return Int(LLVMStoreSizeOfType(llvm, type.asLLVM())) + public func storeSize(of type: IRType) -> Size { + return Size(LLVMStoreSizeOfType(llvm, type.asLLVM())) } /// Computes the pointer size for the platform, optionally in a given @@ -146,12 +129,142 @@ public class TargetData { /// - parameter addressSpace: The address space in which to compute /// pointer size. /// - returns: The size of a pointer in the target address space. - public func pointerSize(addressSpace: Int? = nil) -> Int { - if let addressSpace = addressSpace { - return Int(LLVMPointerSizeForAS(llvm, UInt32(addressSpace))) - } else { - return Int(LLVMPointerSize(llvm)) + public func pointerSize(addressSpace: AddressSpace = .zero) -> Size { + return Size(UInt64(LLVMPointerSizeForAS(llvm, UInt32(addressSpace.rawValue)))) + } + + /// Returns the offset in bytes between successive objects of the + /// specified type, including alignment padding. + /// + /// This is the amount that alloca reserves for this type. For example, + /// returns 12 or 16 for x86_fp80, depending on alignment. + /// + /// - parameter type: The type whose allocation size you wish to compute. + /// - returns: The size an alloca would reserve for the given type. + public func allocationSize(of type: IRType) -> Size { + // Round up to the next alignment boundary. + return TargetData.align(self.storeSize(of: type), to: self.abiAlignment(of: type)) + } + + /// Returns a `StructLayout` object containing the alignment of the + /// struct, its size, and the offsets of its fields with respect to this + /// data layout. + /// + /// - parameter struct: The struct type whose layout you wish to retrieve. + /// - returns: A `StructLayout` describing the layout of the given type. + public func layout(of struct: StructType) -> StructLayout { + guard let cachedLayout = self.structLayoutCache[`struct`.asLLVM()] else { + let layout = StructLayout(`struct`, self) + self.structLayoutCache[`struct`.asLLVM()] = layout + return layout } + return cachedLayout + } + + /// Returns the next integer (mod 2^64) that is greater than or equal to + /// the given size value and is a multiple of the given alignment value. + /// The alignment must be non-zero. + /// + /// If a non-zero skew value is specified, the return value will be a minimal + /// integer that is greater than or equal to the given size value and equal to + /// `align * n + skew` for some integer `n`. If the given skew value is + /// larger than the given alignment value, its value is adjusted to + /// `skew mod alignment`. + /// + /// Computes the next size value that is greater than or equal to the given + /// value and is a multiple of the given alignment. + /// + /// If the skew value is non-zero, the return value will be the next size + /// value that is greater than or equal to the given value multipled by the + /// provided alignment with a skew value added + public static func align(_ value: Size, to align: Alignment, skew: Size = Size.zero) -> Size { + precondition(!align.isZero, "Align can't be 0.") + + let skewValue = skew.rawValue % UInt64(align.rawValue) + let alignValue = UInt64(align.rawValue) + let retVal = (value.rawValue + alignValue - 1 - skewValue) / alignValue * alignValue + skewValue + return Size(retVal) + } +} + +/// A `StructLayout` encapsulates information about the layout of a `StructType`. +public struct StructLayout { + /// Returns the total size of the struct in bytes. + /// + /// If the structure is packed, this returns a value that is effectively + /// the sum of the sizes of its fields. If the structure is not packed, this + /// returns the value of the sum of the sizes of its fields plus any + /// platform-dictated padding. + public let size: Size + /// Returns the alignment of the struct in bytes. + /// + /// The alignment value is effectively the maximum of the alignment of each of + /// its member values. This value will never be zero, as even an empty + /// structure has an alignment of one byte. + public let alignment: Alignment + /// Returns true if the structure type includes padding between elements. + public let isPadded: Bool + /// Returns the number of elements of this structure type. + public let elementCount: Int + /// Returns the offsets of each member from the start of the of the struct in + /// bytes. + public let memberOffsets: [Size] + + fileprivate init(_ st: StructType, _ dl: TargetData) { + assert(!st.isOpaque, "Cannot get layout of opaque structs") + var structAlignment = Alignment.zero + var structSize = Size.zero + var structIsPadded = false + var structMemberOffsets = [Size]() + structMemberOffsets.reserveCapacity(st.elementTypes.count) + self.elementCount = st.elementTypes.count + + // Loop over each of the elements, placing them in memory. + for ty in st.elementTypes { + let tyAlign = st.isPacked ? Alignment.one : dl.abiAlignment(of: ty) + + // Add padding if necessary to align the data element properly. + if (structSize.rawValue & UInt64(tyAlign.rawValue-1)) != 0 { + structIsPadded = true + structSize = TargetData.align(structSize, to: tyAlign) + } + + // Keep track of maximum alignment constraint. + structAlignment = max(tyAlign, structAlignment) + + structMemberOffsets.append(structSize) + // Consume space for this data item + structSize = structSize + dl.allocationSize(of: ty) + } + + // Empty structures have alignment of 1 byte. + if structAlignment == Alignment.zero { + structAlignment = Alignment.one + } + + // Add padding to the end of the struct so that it could be put in an array + // and all array elements would be aligned correctly. + if (structSize.rawValue & UInt64(structAlignment.rawValue-1)) != 0 { + structIsPadded = true + structSize = TargetData.align(structSize, to: structAlignment) + } + self.size = structSize + self.alignment = structAlignment + self.isPadded = structIsPadded + self.memberOffsets = structMemberOffsets + } + + /// Given a valid byte offset into the structure, returns the structure + /// index that contains it. + public func index(of offset: Size) -> Int { + precondition(!self.memberOffsets.isEmpty, + "Cannot compute index member offset of an empty struct type!") + // Multiple fields can have the same offset if any of them are zero sized. + // For example, in { i32, [0 x i32], i32 }, searching for offset 4 will stop + // at the i32 element, because it is the last element at that offset. This is + // the right one to return, because anything after it will have a higher + // offset, implying that this element is non-empty. + return self.memberOffsets.firstIndex(where: { $0 > offset }) ?? self.memberOffsets.endIndex } } @@ -267,16 +380,49 @@ public enum CodeGenOptLevel { } /// The relocation model types supported by LLVM. -public enum RelocMode { +public enum RelocationModel { /// Generated code will assume the default for a particular target architecture. case `default` /// Generated code will exist at static offsets. case `static` - /// Generated code will be Position-Independent. + /// Generated code will be position-independent. case pic - /// Generated code will not be Position-Independent and may be used in static + /// Generated code will not be position-independent and may be used in static /// or dynamic executables but not necessarily a shared library. case dynamicNoPIC + /// Generated code will be compiled in read-only position independent mode. + /// In this mode, all read-only data and functions are at a link-time constant + /// offset from the program counter. + /// + /// ROPI is not supported by all target architectures and calling conventions. + /// It is a particular feature of ARM targets, though. + /// + /// ROPI may be useful to avoid committing to compile-time constant locations + /// for code in memory. This may be useful in the following circumstances: + /// + /// - Code is loaded dynamically. + /// - Code is loaded into memory conditionally, or in an undefined order. + /// - Code is mapped into different addresses during different executions. + case ropi + /// Generated code will be compiled in read-write position independent mode. + /// In this mode, all writable data is at a link-time constant offset from the + /// static base register. + /// + /// RWPI is not supported by all target architectures and calling conventions. + /// It is a particular feature of ARM targets, though. + /// + /// RWPI may be useful to avoid committing to compile-time constant locations + /// for code in memory. This is particularly useful for data that must be + /// multiply instantiated for reentrant routines, as each thread executing a + /// reentrant routine will recieve its own copy of any data in + /// read-write segments. + case rwpi + /// Combines the `ropi` and `rwpi` modes. Generated code will be compiled in + /// both read-only and read-write position independent modes. All read-only + /// data appears at a link-time constant offset from the program counter, + /// and all writable data appears at a link-time constant offset from the + /// static base register. + case ropiRWPI /// Returns the underlying `LLVMRelocMode` associated with this /// relocation model. @@ -286,6 +432,9 @@ public enum RelocMode { case .static: return LLVMRelocStatic case .pic: return LLVMRelocPIC case .dynamicNoPIC: return LLVMRelocDynamicNoPic + case .ropi: return LLVMRelocROPI + case .rwpi: return LLVMRelocRWPI + case .ropiRWPI: return LLVMRelocROPI_RWPI } } } diff --git a/Sources/LLVM/TargetMachine.swift b/Sources/LLVM/TargetMachine.swift index 9c528218..6c6995c9 100644 --- a/Sources/LLVM/TargetMachine.swift +++ b/Sources/LLVM/TargetMachine.swift @@ -75,6 +75,73 @@ public class Target { public init(llvm: LLVMTargetRef) { self.llvm = llvm } + + /// Returns `true` if this target supports just-in-time compilation. + /// + /// Attempting to create a JIT for a `Target` where this predicate is false + /// may lead to program instability or corruption. + public var hasJIT: Bool { + return LLVMTargetHasJIT(self.llvm) != 0 + } + + + /// Returns `true` if this target has a `TargetMachine` associated with it. + /// + /// Target machines are registered by the corresponding initializer functions + /// for each target. LLVMSwift will ensure that these functions are invoked + /// when a TargetMachine is created, but not before. + public var hasTargetMachine: Bool { + return LLVMTargetHasTargetMachine(self.llvm) != 0 + } + + /// Returns `true` if this target has an ASM backend. + /// + /// ASM backends are registered by the corresponding iniailizer functions for + /// each target. LLVMSwift will ensure that these functions are invoked + /// when a TargetMachine is created, but not before. + public var hasASMBackend: Bool { + return LLVMTargetHasAsmBackend(self.llvm) != 0 + } + + /// The name of this target. + public var name: String { + guard let str = LLVMGetTargetName(self.llvm) else { + return "" + } + return String(validatingUTF8: UnsafePointer(str)) ?? "" + } + + /// The description of this target. + public var targetDescription: String { + guard let str = LLVMGetTargetDescription(self.llvm) else { + return "" + } + return String(validatingUTF8: UnsafePointer(str)) ?? "" + } + + /// Returns a sequence of all targets in the global list of targets. + public static var allTargets: AnySequence { + var current = firstTarget + return AnySequence { + return AnyIterator { + defer { current = current?.next() } + return current + } + } + } + + /// Returns the first target in the global target list, if it exists. + public static var firstTarget: Target? { + guard let targetRef = LLVMGetFirstTarget() else { return nil } + return Target(llvm: targetRef) + } + + /// Returns the target following this target in the global target list, + /// if it exists. + public func next() -> Target? { + guard let targetRef = LLVMGetNextTarget(self.llvm) else { return nil } + return Target(llvm: targetRef) + } } /// A `TargetMachine` object represents an object that encapsulates information @@ -89,15 +156,8 @@ public class TargetMachine { /// The data layout semantics associated with this target machine. public let dataLayout: TargetData - /// A string representing the target triple for this target machine. In the - /// form `---` where - /// - /// - arch = x86_64, i386, arm, thumb, mips, etc. - /// - sub = for ex. on ARM: v5, v6m, v7a, v7m, etc. - /// - vendor = pc, apple, nvidia, ibm, etc. - /// - sys = none, linux, win32, darwin, cuda, etc. - /// - abi = eabi, gnu, android, macho, elf, etc. - public let triple: String + /// The target triple for this target machine. + public let triple: Triple /// The CPU associated with this target machine. public var cpu: String { @@ -117,6 +177,8 @@ public class TargetMachine { return String(validatingUTF8: UnsafePointer(str)) ?? "" } + internal var ownsContext: Bool = true + /// Creates a Target Machine with information about its target environment. /// /// - parameter triple: An optional target triple to target. If this is not @@ -127,32 +189,32 @@ public class TargetMachine { /// particular target provides. /// - parameter optLevel: The optimization level for generated code. If no /// value is provided, the default level of optimization is assumed. - /// - parameter relocMode: The relocation mode of the target environment. If - /// no mode is provided, the default mode for the target architecture is + /// - parameter relocations: The relocation model of the target environment. + /// If no mode is provided, the default model for the target architecture is /// assumed. /// - parameter codeModel: The kind of code to produce for this target. If /// no model is provided, the default model for the target architecture is /// assumed. - public init(triple: String? = nil, cpu: String = "", features: String = "", - optLevel: CodeGenOptLevel = .default, relocMode: RelocMode = .default, + public init(triple: Triple = .default, cpu: String = "", features: String = "", + optLevel: CodeGenOptLevel = .default, relocations: RelocationModel = .default, codeModel: CodeModel = .default) throws { // Ensure the LLVM initializer is called when the first module is created initializeLLVM() - self.triple = triple ?? String(cString: LLVMGetDefaultTargetTriple()!) + self.triple = triple var target: LLVMTargetRef? var error: UnsafeMutablePointer? - LLVMGetTargetFromTriple(self.triple, &target, &error) + LLVMGetTargetFromTriple(self.triple.data, &target, &error) if let error = error { defer { LLVMDisposeMessage(error) } - throw TargetMachineError.couldNotCreateTarget(self.triple, + throw TargetMachineError.couldNotCreateTarget(self.triple.data, String(cString: error)) } self.target = Target(llvm: target!) - self.llvm = LLVMCreateTargetMachine(target!, self.triple, cpu, features, + self.llvm = LLVMCreateTargetMachine(target!, self.triple.data, cpu, features, optLevel.asLLVM(), - relocMode.asLLVM(), + relocations.asLLVM(), codeModel.asLLVM()) self.dataLayout = TargetData(llvm: LLVMCreateTargetDataLayout(self.llvm)) } @@ -176,7 +238,7 @@ public class TargetMachine { } var err: UnsafeMutablePointer? let status = path.withCString { cStr -> LLVMBool in - var mutable = strdup(cStr) + let mutable = strdup(cStr) defer { free(mutable) } return LLVMTargetMachineEmitToFile(llvm, module.llvm, mutable, type.asLLVM(), &err) } @@ -216,7 +278,11 @@ public class TargetMachine { return MemoryBuffer(llvm: llvm) } + /// Deinitialize this value and dispose of its resources. deinit { + guard self.ownsContext else { + return + } LLVMDisposeTargetMachine(llvm) } } diff --git a/Sources/LLVM/TokenType.swift b/Sources/LLVM/TokenType.swift index 3e307586..77df8fc5 100644 --- a/Sources/LLVM/TokenType.swift +++ b/Sources/LLVM/TokenType.swift @@ -19,6 +19,12 @@ public struct TokenType: IRType { /// Retrieves the underlying LLVM type object. public func asLLVM() -> LLVMTypeRef { - fatalError("This version of LLVM does not support the creation of TokenType objects") + return LLVMTokenTypeInContext(context.llvm) + } +} + +extension TokenType: Equatable { + public static func == (lhs: TokenType, rhs: TokenType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() } } diff --git a/Sources/LLVM/Triple.swift b/Sources/LLVM/Triple.swift new file mode 100644 index 00000000..325671d0 --- /dev/null +++ b/Sources/LLVM/Triple.swift @@ -0,0 +1,1399 @@ +#if SWIFT_PACKAGE +import cllvm +import llvmshims +#endif + +/// A `Triple` provides an abstraction over "Target Triples". +/// +/// A Target Triple encodes information about the target of a +/// compilation session including the underlying processor architecture, OS, +/// platform vendor, and additional information about the runtime environment. +/// +/// A target triple is usually specified at the command line as a `-` delimited +/// string in the format: +/// +/// --- +/// +/// For example: +/// +/// nvptx64-nvidia-cuda +/// x86_64-unknown-linux-gnu +/// x86_64-apple-ios8.3-simulator +/// +/// For this reason, `Triple` provides an initializer that parses strings in +/// this format. +public struct Triple: Equatable { + /// The raw target triple string. + public let data: String + /// The target's architecture. + public let architecture: Architecture + /// The target's vendor. + public let vendor: Vendor + /// The target's operating system. + public let os: OS + /// The target's environment. + public let environment: Environment + /// The target's object file format. + public let objectFormat: ObjectFormat + + /// Returns the default target triple for the host machine. + public static let `default`: Triple = { + guard let raw = LLVMGetDefaultTargetTriple() else { + return Triple("") + } + defer { LLVMDisposeMessage(raw) } + return Triple(String(cString: raw)) + }() + + /// Create a target triple from known components. + /// + /// - Parameters: + /// - architecture: The target's architecture. If none is specified, + /// an unknown architecture is assumed. + /// - vendor: The target's vendor. If none is specified, + /// an unknown vendor is assumed. + /// - os: The target's operating system. If none is specified, + /// an unknown operating system is assumed. + /// - environment: The target's environment. If none is specified, + /// an unknown environment is assumed. + /// - objectFormat: The target's object file format. If none is specified, + /// an unknown object file format is assumed. + public init( + architecture: Architecture = .unknown, + vendor: Vendor = .unknown, + os: OS = .unknown, + environment: Environment = .unknown, + objectFormat: ObjectFormat = .unknown + ) { + self.data = [ + architecture.rawValue, + vendor.rawValue, + os.rawValue, + environment.rawValue + ].joined(separator: "-") + + self.architecture = architecture + self.vendor = vendor + self.os = os + self.environment = environment + self.objectFormat = (objectFormat == .unknown) + ? ObjectFormat.default(for: architecture, os: os) + : objectFormat + } + + /// Create a target triple by parsing a string in the standard LLVM + /// triple format. + /// + /// The expected format of a target triple string is as follows: + /// + /// --- + /// + /// - Parameter str: The target triple format string to parse. + public init(_ str: String) { + var parch: Architecture = .unknown + var pvendor: Vendor = .unknown + var pos: OS = .unknown + var penvironment: Environment = .unknown + var pobjectFormat: ObjectFormat = .unknown + + let components = str.split(separator: "-", maxSplits: 3, omittingEmptySubsequences: false) + if components.count > 0 { + parch = Architecture(parse: components[0]) + if components.count > 1 { + pvendor = Vendor(parse: components[1]) + if components.count > 2 { + pos = OS(parse: components[2]) + if components.count > 3 { + penvironment = Environment(parse: components[3]) + pobjectFormat = ObjectFormat(parse: components[3]) + } + } + } else { + switch components[0] { + case let x where x.starts(with: "mipsn32"): + penvironment = .gnuABIN32 + case let x where x.starts(with: "mips64"): + penvironment = .gnuABI64 + case let x where x.starts(with: "mipsisa64"): + penvironment = .gnuABI64 + case let x where x.starts(with: "mipsisa32"): + penvironment = .gnu + case "mips", "mipsel", "mipsr6", "mipsr6el": + penvironment = .gnu + default: + penvironment = .unknown + } + pvendor = .unknown + } + } else { + parch = .unknown + } + + if pobjectFormat == .unknown { + pobjectFormat = ObjectFormat.default(for: parch, os: pos) + } + + self.data = str + self.architecture = parch + self.vendor = pvendor + self.os = pos + self.environment = penvironment + self.objectFormat = pobjectFormat + } + + /// Create a target triple from string components. + /// + /// The environment is assumed to be unknown and the object file format is + /// determined from a combination of the given target architecture and + /// operating system. + /// + /// - Parameters: + /// - arch: The target's architecture. + /// - vendor: The target's vendor + /// - os: The target's operating system. + public init(arch: String, vendor: String, os: String) { + self.data = [arch, vendor, os].joined(separator: "-") + self.architecture = Architecture(parse: Substring(arch)) + self.vendor = Vendor(parse: Substring(vendor)) + self.os = OS(parse: Substring(os)) + self.environment = .unknown + self.objectFormat = ObjectFormat.default(for: self.architecture, os: self.os) + } + + /// Create a target triple from string components. + /// + /// - Parameters: + /// - arch: The target's architecture. + /// - vendor: The target's vendor + /// - os: The target's operating system. + /// - environment: The target's environment. + public init(arch: String, vendor: String, os: String, environment: String) { + self.data = [arch, vendor, os, environment].joined(separator: "-") + self.architecture = Architecture(parse: Substring(arch)) + self.vendor = Vendor(parse: Substring(vendor)) + self.os = OS(parse: Substring(os)) + self.environment = Environment(parse: Substring(environment)) + self.objectFormat = ObjectFormat(parse: Substring(environment)) + } + + public static func == (lhs: Triple, rhs: Triple) -> Bool { + return lhs.data == rhs.data + && lhs.architecture == rhs.architecture + && lhs.vendor == rhs.vendor + && lhs.os == rhs.os + && lhs.environment == rhs.environment + && lhs.objectFormat == rhs.objectFormat + } + + /// Normalizes a target triple format string. + /// + /// The normalization process converts an arbitrary machine specification + /// into the canonical triple form. In particular, it handles the + /// common case in which otherwise valid components are in the wrong order. + /// + /// Examples: + /// + /// Triple.normalize("---") == "unknown-unknown-unknown-unknown" + /// Triple.normalize("-pc-i386") == "i386-pc-unknown" + /// Triple.normalize("a-b-c-i386") == "i386-a-b-c" + /// + /// - Parameter string: The target triple format string. + /// - Returns: A normalized target triple string. + public static func normalize(_ string: String) -> String { + guard let data = LLVMNormalizeTargetTriple(string) else { + return "" + } + defer { LLVMDisposeMessage(data) } + return String(cString: data) + } + + /// Returns the architecture component of the triple, if it exists. + /// + /// If the environment component does not exist, the empty string is returned. + public var architectureName: Substring { + let split = self.data.split(separator: "-", maxSplits: 3, omittingEmptySubsequences: false) + guard split.count > 0 else { + return "" + } + return split[0] + } + + /// Returns the vendor component of the triple, if it exists. + /// + /// If the environment component does not exist, the empty string is returned. + public var vendorName: Substring { + let split = self.data.split(separator: "-", maxSplits: 3, omittingEmptySubsequences: false) + guard split.count > 1 else { + return "" + } + return split[1] + } + + /// Returns the operating system component of the triple, if it exists. + /// + /// If the environment component does not exist, the empty string is returned. + public var osName: Substring { + let split = self.data.split(separator: "-", maxSplits: 3, omittingEmptySubsequences: false) + guard split.count > 2 else { + return "" + } + return split[2] + } + + /// Returns the environment component of the triple, if it exists. + /// + /// If the environment component does not exist, the empty string is returned. + public var environmentName: Substring { + let split = self.data.split(separator: "-", maxSplits: 3, omittingEmptySubsequences: false) + guard split.count > 3 else { + return "" + } + return split[3] + } +} + +extension Triple { + /// Returns whether this environment is a simulator. + public var isSimulatorEnvironment: Bool { + return self.environment == .simulator + } + + /// Returns whether this environment is a Windows OS in an MSVC environment. + public var isKnownWindowsMSVCEnvironment: Bool { + return self.os.isWindows && self.environment == .msvc + } + + /// Checks if the environment could be MSVC. + public var isWindowsMSVCEnvironment: Bool { + return self.isKnownWindowsMSVCEnvironment || + (self.os.isWindows && self.environment == .unknown) + } + + /// Returns whether this environment is a Windows OS in a CoreCLR environment. + public var isWindowsCoreCLREnvironment: Bool { + return self.os.isWindows && self.environment == .coreCLR + } + + /// Returns whether this environment is a Windows OS in an + /// Itanium environment. + public var isWindowsItaniumEnvironment: Bool { + return self.os.isWindows && self.environment == .itanium + } + + /// Returns whether this environment is a Windows OS in a Cygnus environment. + public var isWindowsCygwinEnvironment: Bool { + return self.os.isWindows && self.environment == .cygnus + } + + /// Returns whether this environment is a Windows OS in a GNU environment. + public var isWindowsGNUEnvironment: Bool { + return self.os.isWindows && self.environment == .gnu + } + + /// Returns whether the OS uses glibc. + public var isOSGlibc: Bool { + return (self.os == .linux || self.os == .kFreeBSD || + self.os == .hurd) && + !self.isAndroid + } + + /// Tests for either Cygwin or MinGW OS + public var isOSCygMing: Bool { + return self.isWindowsCygwinEnvironment || self.isWindowsGNUEnvironment + } + + /// Is this a "Windows" OS targeting a "MSVCRT.dll" environment. + public var isOSMSVCRT: Bool { + return self.isWindowsMSVCEnvironment || self.isWindowsGNUEnvironment || + self.isWindowsItaniumEnvironment + } + + /// Returns whether the OS uses the ELF binary format. + public var isOSBinFormatELF: Bool { + return self.objectFormat == .elf + } + + /// Returns whether the OS uses the COFF binary format. + public var isOSBinFormatCOFF: Bool { + return self.objectFormat == .coff + } + + /// Returns whether the environment is MachO. + public var isOSBinFormatMachO: Bool { + return self.objectFormat == .machO + } + + /// Returns whether the OS uses the Wasm binary format. + public var isOSBinFormatWasm: Bool { + return self.objectFormat == .wasm + } + + /// Returns whether the OS uses the XCOFF binary format. + public var isOSBinFormatXCOFF: Bool { + return self.objectFormat == .xcoff + } + + /// Returns whether the target is the PS4 CPU + public var isPS4CPU: Bool { + return self.architecture == .x86_64 && + self.vendor == .scei && + self.os == .ps4 + } + + /// Returns whether the target is the PS4 platform + public var isPS4: Bool { + return self.vendor == .scei && + self.os == .ps4 + } + + /// Returns whether the target is Android + public var isAndroid: Bool { + return self.environment == .android + } + + /// Returns whether the environment is musl-libc + public var isMusl: Bool { + return self.environment == .musl || + self.environment == .muslEABI || + self.environment == .muslEABIHF + } + + /// Returns whether the target is NVPTX (32- or 64-bit). + public var isNVPTX: Bool { + return self.architecture == .nvptx || self.architecture == .nvptx64 + } + + /// Returns whether the target is Thumb (little and big endian). + public var isThumb: Bool { + return self.architecture == .thumb || self.architecture == .thumbeb + } + + /// Returns whether the target is ARM (little and big endian). + public var isARM: Bool { + return self.architecture == .arm || self.architecture == .armeb + } + + /// Returns whether the target is AArch64 (little and big endian). + public var isAArch64: Bool { + return self.architecture == .aarch64 || self.architecture == .aarch64_be + } + + /// Returns whether the target is MIPS 32-bit (little and big endian). + public var isMIPS32: Bool { + return self.architecture == .mips || self.architecture == .mipsel + } + + /// Returns whether the target is MIPS 64-bit (little and big endian). + public var isMIPS64: Bool { + return self.architecture == .mips64 || self.architecture == .mips64el + } + + /// Returns whether the target is MIPS (little and big endian, 32- or 64-bit). + public var isMIPS: Bool { + return self.isMIPS32 || self.isMIPS64 + } + + /// Returns whether the target supports comdat + public var supportsCOMDAT: Bool { + return !self.isOSBinFormatMachO + } + + /// Returns whether the target uses emulated TLS as default. + public var hasDefaultEmulatedTLS: Bool { + return self.isAndroid || self.os.isOpenBSD || self.isWindowsCygwinEnvironment + } +} + +// MARK: Triple Data + +extension Triple { + /// Represents an architecture known to LLVM. + public enum Architecture: String, CaseIterable { + /// An unknown architecture or hardware platform. + case unknown = "unknown" + + /// ARM (little endian): arm, armv.*, xscale + case arm = "arm" + /// ARM (big endian): armeb + case armeb = "armeb" + /// AArch64 (little endian): aarch64 + case aarch64 = "aarch64" + /// AArch64 (big endian): aarch64_be + case aarch64_be = "aarch64_be" + /// ARC: Synopsys ARC + case arc = "arc" + /// AVR: Atmel AVR microcontroller + case avr = "avr" + /// eBPF or extended BPF or 64-bit BPF (little endian) + case bpfel = "bpfel" + /// eBPF or extended BPF or 64-bit BPF (big endian) + case bpfeb = "bpfeb" + /// Hexagon: hexagon + case hexagon = "hexagon" + /// MIPS: mips, mipsallegrex, mipsr6 + case mips = "mips" + /// MIPSEL: mipsel, mipsallegrexe, mipsr6el + case mipsel = "mipsel" + /// MIPS64: mips64, mips64r6, mipsn32, mipsn32r6 + case mips64 = "mips64" + /// MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el + case mips64el = "mips64el" + /// MSP430: msp430 + case msp430 = "msp430" + /// PPC: powerpc + case ppc = "ppc" + /// PPC64: powerpc64, ppu + case ppc64 = "ppc64" + /// PPC64LE: powerpc64le + case ppc64le = "ppc64le" + /// R600: AMD GPUs HD2XXX - HD6XXX + case r600 = "r600" + /// AMDGCN: AMD GCN GPUs + case amdgcn = "amdgcn" + /// RISC-V (32-bit): riscv32 + case riscv32 = "riscv32" + /// RISC-V (64-bit): riscv64 + case riscv64 = "riscv64" + /// Sparc: sparc + case sparc = "sparc" + /// Sparcv9: Sparcv9 + case sparcv9 = "sparcv9" + /// Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant + case sparcel = "sparcel" + /// SystemZ: s390x + case systemz = "systemz" + /// TCE (http://tce.cs.tut.fi/): tce + case tce = "tce" + /// TCE little endian (http://tce.cs.tut.fi/): tcele + case tcele = "tcele" + /// Thumb (little endian): thumb, thumbv.* + case thumb = "thumb" + /// Thumb (big endian): thumbeb + case thumbeb = "thumbeb" + /// X86: i[3-9]86 + case x86 = "x86" + /// X86-64: amd64, x86_64 + case x86_64 = "x86_64" + /// XCore: xcore + case xcore = "xcore" + /// NVPTX: 32-bit + case nvptx = "nvptx" + /// NVPTX: 64-bit + case nvptx64 = "nvptx64" + /// le32: generic little-endian 32-bit CPU (PNaCl) + case le32 = "le32" + /// le64: generic little-endian 64-bit CPU (PNaCl) + case le64 = "le64" + /// AMDIL + case amdil = "amdil" + /// AMDIL with 64-bit pointers + case amdil64 = "amdil64" + /// AMD HSAIL + case hsail = "hsail" + /// AMD HSAIL with 64-bit pointers + case hsail64 = "hsail64" + /// SPIR: standard portable IR for OpenCL 32-bit version + case spir = "spir" + /// SPIR: standard portable IR for OpenCL 64-bit version + case spir64 = "spir64" + /// Kalimba: generic kalimba + case kalimba = "kalimba" + /// SHAVE: Movidius vector VLIW processors + case shave = "shave" + /// Lanai: Lanai 32-bit + case lanai = "lanai" + /// WebAssembly with 32-bit pointers + case wasm32 = "wasm32" + /// WebAssembly with 64-bit pointers + case wasm64 = "wasm64" + /// 32-bit RenderScript + case renderscript32 = "renderscript32" + /// 64-bit RenderScript + case renderscript64 = "renderscript64" + + fileprivate init(parse archName: Substring) { + func parseBPFArch(_ ArchName: Substring) -> Architecture { + if ArchName == "bpf" { + #if _endian(little) + return .bpfel + #elseif _endian(big) + return .bpfeb + #else + #error("Unknown endianness?") + #endif + } else if ArchName == "bpf_be" || ArchName == "bpfeb" { + return .bpfeb + } else if ArchName == "bpf_le" || ArchName == "bpfel" { + return .bpfel + } else { + return .unknown + } + } + + func parseARMArch(_ ArchName: Substring) -> Architecture { + enum ARMISA { + case invalid + case arm + case thumb + case aarch64 + } + func parseISA(_ Arch: Substring) -> ARMISA { + switch Arch { + case let x where x.starts(with: "aarch64"): + return .aarch64 + case let x where x.starts(with: "arm64"): + return .aarch64 + case let x where x.starts(with: "thumb"): + return .thumb + case let x where x.starts(with: "arm"): + return .arm + default: + return .invalid + } + } + + enum EndianKind { + case invalid + case little + case big + } + + func parseArchEndian(_ Arch: Substring) -> EndianKind { + if (Arch.starts(with: "armeb") || Arch.starts(with: "thumbeb") || + Arch.starts(with: "aarch64_be")) { + return .big + } + + if Arch.starts(with: "arm") || Arch.starts(with: "thumb") { + if Arch.hasSuffix("eb") { + return .big + } else { + return .little + } + } + + if Arch.starts(with: "aarch64") { + return .little + } + + return .invalid + } + + let isa = parseISA(archName) + let endian = parseArchEndian(archName) + + var arch = Architecture.unknown + switch endian { + case .little: + switch isa { + case .arm: + arch = .arm + case .thumb: + arch = .thumb + case .aarch64: + arch = .aarch64 + case .invalid: + break + } + case .big: + switch isa { + case .arm: + arch = .armeb + case .thumb: + arch = .thumbeb + case .aarch64: + arch = .aarch64_be + case .invalid: + break + } + case .invalid: + break + } + + let ownedStr = String(archName) + guard let rawArch = LLVMGetARMCanonicalArchName(ownedStr, ownedStr.count) else { + fatalError() + } + let archName = String(cString: rawArch) + guard !archName.isEmpty else { + return .unknown + } + // Thumb only exists in v4+ + if isa == .thumb && (ArchName.starts(with: "v2") || ArchName.starts(with: "v3")) { + return .unknown + } + + // Thumb only for v6m + let Profile = LLVMARMParseArchProfile(archName, archName.count) + let Version = LLVMARMParseArchVersion(archName, archName.count) + if Profile == LLVMARMProfileKindM && Version == 6 { + if endian == .big { + return .thumbeb + } else { + return .thumb + } + } + + return arch + } + + switch archName { + case "i386", "i486", "i586", "i686": + self = .x86 + // FIXME: Do we need to support these? + case "i786", "i886", "i986": + self = .x86 + case "amd64", "x86_64", "x86_64h": + self = .x86_64 + case "powerpc", "ppc", "ppc32": + self = .ppc + case "powerpc64", "ppu", "ppc64": + self = .ppc64 + case "powerpc64le", "ppc64le": + self = .ppc64le + case "xscale": + self = .arm + case "xscaleeb": + self = .armeb + case "aarch64": + self = .aarch64 + case "aarch64_be": + self = .aarch64_be + case "arc": + self = .arc + case "arm64": + self = .aarch64 + case "arm": + self = .arm + case "armeb": + self = .armeb + case "thumb": + self = .thumb + case "thumbeb": + self = .thumbeb + case "avr": + self = .avr + case "msp430": + self = .msp430 + case "mips", "mipseb", "mipsallegrex", "mipsisa32r6", "mipsr6": + self = .mips + case "mipsel", "mipsallegrexel", "mipsisa32r6el", "mipsr6el": + self = .mipsel + case "mips64", "mips64eb", "mipsn32", "mipsisa64r6", "mips64r6", "mipsn32r6": + self = .mips64 + case "mips64el", "mipsn32el", "mipsisa64r6el", "mips64r6el", "mipsn32r6el": + self = .mips64el + case "r600": + self = .r600 + case "amdgcn": + self = .amdgcn + case "riscv32": + self = .riscv32 + case "riscv64": + self = .riscv64 + case "hexagon": + self = .hexagon + case "s390x", "systemz": + self = .systemz + case "sparc": + self = .sparc + case "sparcel": + self = .sparcel + case "sparcv9", "sparc64": + self = .sparcv9 + case "tce": + self = .tce + case "tcele": + self = .tcele + case "xcore": + self = .xcore + case "nvptx": + self = .nvptx + case "nvptx64": + self = .nvptx64 + case "le32": + self = .le32 + case "le64": + self = .le64 + case "amdil": + self = .amdil + case "amdil64": + self = .amdil64 + case "hsail": + self = .hsail + case "hsail64": + self = .hsail64 + case "spir": + self = .spir + case "spir64": + self = .spir64 + case let x where x.starts(with: "kalimba"): + self = .kalimba + case "lanai": + self = .lanai + case "shave": + self = .shave + case "wasm32": + self = .wasm32 + case "wasm64": + self = .wasm64 + case "renderscript32": + self = .renderscript32 + case "renderscript64": + self = .renderscript64 + default: + if archName.starts(with: "arm") || archName.starts(with: "thumb") || archName.starts(with: "aarch64") { + self = parseARMArch(archName) + } else if archName.starts(with: "bpf") { + self = parseBPFArch(archName) + } else { + self = .unknown + } + } + } + + /// Returns the prefix for a family of related architectures. + public var prefix: String { + switch self { + case .aarch64, .aarch64_be: + return "aarch64" + case .arc: + return "arc" + case .arm, .armeb, .thumb, .thumbeb: + return "arm" + case .avr: + return "avr" + case .ppc64, .ppc64le, .ppc: + return "ppc" + case .mips, .mipsel, .mips64, .mips64el: + return "mips" + case .hexagon: + return "hexagon" + case .amdgcn: + return "amdgcn" case .r600: + return "r600" + case .bpfel, .bpfeb: + return "bpf" + case .sparcv9, .sparcel, .sparc: + return "sparc" + case .systemz: + return "s390" + case .x86, .x86_64: + return "x86" + case .xcore: + return "xcore" + // NVPTX intrinsics are namespaced under nvvm. + case .nvptx, .nvptx64: + return "nvvm" + case .le32: + return "le32" + case .le64: + return "le64" + case .amdil, .amdil64: + return "amdil" + case .hsail, .hsail64: + return "hsail" + case .spir, .spir64: + return "spir" case .kalimba: + return "kalimba" + case .lanai: + return "lanai" + case .shave: + return "shave" + case .wasm32, .wasm64: + return "wasm" + case .riscv32, .riscv64: + return "riscv" + default: + return "" + } + } + + /// Returns the width in bits for a pointer on this architecture. + public var pointerBitWidth: Int { + switch self { + case .unknown: + return 0 + + case .avr, .msp430: + return 16 + + case .arc: fallthrough + case .arm: fallthrough + case .armeb: fallthrough + case .hexagon: fallthrough + case .le32: fallthrough + case .mips: fallthrough + case .mipsel: fallthrough + case .nvptx: fallthrough + case .ppc: fallthrough + case .r600: fallthrough + case .riscv32: fallthrough + case .sparc: fallthrough + case .sparcel: fallthrough + case .tce: fallthrough + case .tcele: fallthrough + case .thumb: fallthrough + case .thumbeb: fallthrough + case .x86: fallthrough + case .xcore: fallthrough + case .amdil: fallthrough + case .hsail: fallthrough + case .spir: fallthrough + case .kalimba: fallthrough + case .lanai: fallthrough + case .shave: fallthrough + case .wasm32: fallthrough + case .renderscript32: + return 32 + + case .aarch64: fallthrough + case .aarch64_be: fallthrough + case .amdgcn: fallthrough + case .bpfel: fallthrough + case .bpfeb: fallthrough + case .le64: fallthrough + case .mips64: fallthrough + case .mips64el: fallthrough + case .nvptx64: fallthrough + case .ppc64: fallthrough + case .ppc64le: fallthrough + case .riscv64: fallthrough + case .sparcv9: fallthrough + case .systemz: fallthrough + case .x86_64: fallthrough + case .amdil64: fallthrough + case .hsail64: fallthrough + case .spir64: fallthrough + case .wasm64: fallthrough + case .renderscript64: + return 64 + } + } + } + + /// Represents a vendor known to LLVM. + public enum Vendor: String, CaseIterable { + /// An unknown vendor. + case unknown = "unknown" + + /// Apple + case apple = "Apple" + /// PC + case pc = "PC" + /// SCEI + case scei = "SCEI" + /// BGP + case bgp = "BGP" + /// BGQ + case bgq = "BGQ" + /// Freescale + case freescale = "Freescale" + /// IBM + case ibm = "IBM" + /// ImaginationTechnologies + case imaginationTechnologies = "ImaginationTechnologies" + /// MipsTechnologies + case mipsTechnologies = "MipsTechnologies" + /// NVIDIA + case nvidia = "NVIDIA" + /// CSR + case csr = "CSR" + /// Myriad + case myriad = "Myriad" + /// AMD + case amd = "AMD" + /// Mesa + case mesa = "Mesa" + /// SUSE + case suse = "SUSE" + /// OpenEmbedded + case openEmbedded = "OpenEmbedded" + + fileprivate init(parse VendorName: Substring) { + switch VendorName { + case "apple": + self = .apple + case "pc": + self = .pc + case "scei": + self = .scei + case "bgp": + self = .bgp + case "bgq": + self = .bgq + case "fsl": + self = .freescale + case "ibm": + self = .ibm + case "img": + self = .imaginationTechnologies + case "mti": + self = .mipsTechnologies + case "nvidia": + self = .nvidia + case "csr": + self = .csr + case "myriad": + self = .myriad + case "amd": + self = .amd + case "mesa": + self = .mesa + case "suse": + self = .suse + case "oe": + self = .openEmbedded + default: + self = .unknown + } + } + } + + /// Represents an operating system known to LLVM. + public enum OS: String, CaseIterable { + /// An unknown operating system. + case unknown = "UnknownOS" + + /// The Ananas operating system. + case ananas = "Ananas" + /// The CloudABI operating system. + case cloudABI = "CloudABI" + /// The Darwin operating system. + case darwin = "Darwin" + /// The DragonFly operating system. + case dragonFly = "DragonFly" + /// The FreeBSD operating system. + case freeBSD = "FreeBSD" + /// The Fuchsia operating system. + case fuchsia = "Fuchsia" + /// The iOS operating system. + case iOS = "IOS" + /// The GNU/kFreeBSD operating system. + case kFreeBSD = "KFreeBSD" + /// The Linux operating system. + case linux = "Linux" + /// Sony's PS3 operating system. + case lv2 = "Lv2" + /// The macOS operating system. + case macOS = "MacOSX" + /// The NetBSD operating system. + case netBSD = "NetBSD" + /// The OpenBSD operating system. + case openBSD = "OpenBSD" + /// The Solaris operating system. + case solaris = "Solaris" + /// The Win32 operating system. + case win32 = "Win32" + /// The Haiku operating system. + case haiku = "Haiku" + /// The Minix operating system. + case minix = "Minix" + /// The RTEMS operating system. + case rtems = "RTEMS" + /// Native Client + case naCl = "NaCl" + /// BG/P Compute-Node Kernel + case cnk = "CNK" + /// The AIX operating system. + case aix = "AIX" + /// NVIDIA CUDA + case cuda = "CUDA" + /// NVIDIA OpenCL + case nvcl = "NVCL" + /// AMD HSA Runtime + case amdHSA = "AMDHSA" + /// Sony's PS4 operating system. + case ps4 = "PS4" + /// The Intel MCU operating system. + case elfIAMCU = "ELFIAMCU" + /// Apple tvOS. + case tvOS = "TvOS" + /// Apple watchOS. + case watchOS = "WatchOS" + /// The Mesa 3D compute kernel. + case mesa3D = "Mesa3D" + /// The Contiki operating system. + case contiki = "Contiki" + /// AMD PAL Runtime. + case amdPAL = "AMDPAL" + /// HermitCore Unikernel/Multikernel. + case hermitCore = "HermitCore" + /// GNU/Hurd. + case hurd = "Hurd" + /// Experimental WebAssembly OS + case wasi = "WASI" + + fileprivate init(parse OSName: Substring) { + switch OSName { + case let x where x.starts(with: "ananas"): + self = .ananas + case let x where x.starts(with: "cloudabi"): + self = .cloudABI + case let x where x.starts(with: "darwin"): + self = .darwin + case let x where x.starts(with: "dragonfly"): + self = .dragonFly + case let x where x.starts(with: "freebsd"): + self = .freeBSD + case let x where x.starts(with: "fuchsia"): + self = .fuchsia + case let x where x.starts(with: "ios"): + self = .tvOS + case let x where x.starts(with: "kfreebsd"): + self = .kFreeBSD + case let x where x.starts(with: "linux"): + self = .linux + case let x where x.starts(with: "lv2"): + self = .lv2 + case let x where x.starts(with: "macos"): + self = .macOS + case let x where x.starts(with: "netbsd"): + self = .netBSD + case let x where x.starts(with: "openbsd"): + self = .openBSD + case let x where x.starts(with: "solaris"): + self = .solaris + case let x where x.starts(with: "win32"): + self = .win32 + case let x where x.starts(with: "windows"): + self = .win32 + case let x where x.starts(with: "haiku"): + self = .haiku + case let x where x.starts(with: "minix"): + self = .minix + case let x where x.starts(with: "rtems"): + self = .rtems + case let x where x.starts(with: "nacl"): + self = .naCl + case let x where x.starts(with: "cnk"): + self = .cnk + case let x where x.starts(with: "aix"): + self = .aix + case let x where x.starts(with: "cuda"): + self = .cuda + case let x where x.starts(with: "nvcl"): + self = .nvcl + case let x where x.starts(with: "amdhsa"): + self = .amdHSA + case let x where x.starts(with: "ps4"): + self = .ps4 + case let x where x.starts(with: "elfiamcu"): + self = .elfIAMCU + case let x where x.starts(with: "tvos"): + self = .tvOS + case let x where x.starts(with: "watchos"): + self = .watchOS + case let x where x.starts(with: "mesa3d"): + self = .mesa3D + case let x where x.starts(with: "contiki"): + self = .contiki + case let x where x.starts(with: "amdpal"): + self = .amdPAL + case let x where x.starts(with: "hermit"): + self = .hermitCore + case let x where x.starts(with: "hurd"): + self = .hurd + case let x where x.starts(with: "wasi"): + self = .wasi + default: + self = .unknown + } + } + + /// Returns whether the OS is unknown. + public var isUnknown: Bool { + return self == .unknown + } + + /// Returns whether this a Mac OS X triple. + /// + /// For legacy reasons, LLVM supports both "darwin" and "osx" as + /// macOS triples. + public var isMacOS: Bool { + return self == .darwin || self == .macOS + } + + /// Returns whether this an iOS triple. + public var isiOS: Bool { + return self == .iOS || self.isTvOS + } + + /// Returns whether this an Apple tvOS triple. + public var isTvOS: Bool { + return self == .tvOS + } + + /// Returns whether this an Apple watchOS triple. + public var isWatchOS: Bool { + return self == .watchOS + } + + /// Returns whether this a "Darwin" OS (OS X, iOS, or watchOS). + public var isDarwin: Bool { + return self.isMacOS || self.isiOS || self.isWatchOS + } + + /// Returns whether the OS is NetBSD. + public var isNetBSD: Bool { + return self == .netBSD + } + + /// Returns whether the OS is OpenBSD. + public var isOpenBSD: Bool { + return self == .openBSD + } + + /// Returns whether the OS is FreeBSD. + public var isFreeBSD: Bool { + return self == .freeBSD + } + + /// Returns whether the OS is Fuchsia. + public var isFuchsia: Bool { + return self == .fuchsia + } + + /// Returns whether the OS is DragonFly. + public var isDragonFly: Bool { + return self == .dragonFly + } + + /// Returns whether the OS is Solaris. + public var isSolaris: Bool { + return self == .solaris + } + + /// Returns whether the OS is IAMCU. + public var isIAMCU: Bool { + return self == .elfIAMCU + } + + /// Returns whether the OS is Contiki. + public var isContiki: Bool { + return self == .contiki + } + + /// Returns whether the OS is Haiku. + public var isHaiku: Bool { + return self == .haiku + } + + /// Returns whether the OS is Windows. + public var isWindows: Bool { + return self == .win32 + } + + /// Returns whether the OS is NaCl (Native Client) + public var isNaCl: Bool { + return self == .naCl + } + + /// Returns whether the OS is Linux. + public var isLinux: Bool { + return self == .linux + } + + /// Returns whether the OS is kFreeBSD. + public var isKFreeBSD: Bool { + return self == .kFreeBSD + } + + /// Returns whether the OS is Hurd. + public var isHurd: Bool { + return self == .hurd + } + + /// Returns whether the OS is WASI. + public var isWASI: Bool { + return self == .wasi + } + + /// Returns whether the OS is AIX. + public var isAIX: Bool { + return self == .aix + } + } + + /// Represents a runtime environment known to LLVM. + public enum Environment: String, CaseIterable { + /// An unknown environment. + case unknown = "UnknownEnvironment" + + /// The generic GNU environment. + case gnu = "GNU" + /// The GNU environment with 32-bit pointers and integers. + case gnuABIN32 = "GNUABIN32" + /// The GNU environment with 64-bit pointers and integers. + case gnuABI64 = "GNUABI64" + /// The GNU environment for ARM EABI. + /// + /// Differs from `gnuEABIHF` because it uses software floating point. + case gnuEABI = "GNUEABI" + /// The GNU environment for ARM EABI. + /// + /// Differs from `gnuEABI` because it uses hardware floating point. + case gnuEABIHF = "GNUEABIHF" + /// The GNU X32 environment for amd64/x86_64 CPUs using 32-bit integers, + /// longs and pointers. + case gnuX32 = "GNUX32" + /// The _ environment. + case code16 = "CODE16" + /// The ARM EABI environment. + /// + /// Differs from `eabiHF` because it uses software floating point. + case eabi = "EABI" + /// The ARM EABI environment. + /// + /// Differs from `eabi` because it uses hardware floating point. + case eabiHF = "EABIHF" + /// The Google Android environment. + case android = "Android" + /// The musl environment. + case musl = "Musl" + /// The musl environment for ARM EABI. + /// + /// Differs from `muslEABIHF` because it uses software floating point. + case muslEABI = "MuslEABI" + /// The musl environment for ARM EABI. + /// + /// Differs from `Differs` because it uses hardware floating point. + case muslEABIHF = "MuslEABIHF" + /// The Microsoft Visual C++ environment. + case msvc = "MSVC" + /// The Intel Itanium environment. + case itanium = "Itanium" + /// The Cygnus environment. + case cygnus = "Cygnus" + /// The Microsoft CoreCLR environment for .NET core. + case coreCLR = "CoreCLR" + /// Simulator variants of other systems, e.g., Apple's iOS + case simulator = "Simulator" + + fileprivate init(parse EnvironmentName: Substring) { + switch EnvironmentName { + case let x where x.starts(with: "eabihf"): + self = .eabiHF + case let x where x.starts(with: "eabi"): + self = .eabi + case let x where x.starts(with: "gnuabin32"): + self = .gnuABIN32 + case let x where x.starts(with: "gnuabi64"): + self = .gnuABI64 + case let x where x.starts(with: "gnueabihf"): + self = .gnuEABIHF + case let x where x.starts(with: "gnueabi"): + self = .gnuEABI + case let x where x.starts(with: "gnux32"): + self = .gnuX32 + case let x where x.starts(with: "code16"): + self = .code16 + case let x where x.starts(with: "gnu"): + self = .gnu + case let x where x.starts(with: "android"): + self = .android + case let x where x.starts(with: "musleabihf"): + self = .muslEABIHF + case let x where x.starts(with: "musleabi"): + self = .muslEABI + case let x where x.starts(with: "musl"): + self = .musl + case let x where x.starts(with: "msvc"): + self = .msvc + case let x where x.starts(with: "itanium"): + self = .itanium + case let x where x.starts(with: "cygnus"): + self = .cygnus + case let x where x.starts(with: "coreclr"): + self = .coreCLR + case let x where x.starts(with: "simulator"): + self = .simulator + default: + self = .unknown + } + } + + /// Returns whether this environment is a GNU environment. + public var isGNU: Bool { + return self == .gnu || self == .gnuABIN32 || + self == .gnuABI64 || self == .gnuEABI || + self == .gnuEABIHF || self == .gnuX32 + } + } + + /// Represents an object file format known to LLVM. + public enum ObjectFormat: String, CaseIterable { + /// An unknown object file format. + case unknown = "unknown" + + /// The Common Object File Format. + case coff = "COFF" + /// The Executable and Linkable Format. + case elf = "ELF" + /// The Mach Object format. + case machO = "MachO" + /// The Web Assembly format. + case wasm = "Wasm" + /// The eXtended Common Object File Format. + case xcoff = "XCOFF" + + fileprivate init(parse EnvironmentName: Substring) { + switch EnvironmentName { + // "xcoff" must come before "coff" because of the order-dependendent + // pattern matching. + case let x where x.hasSuffix("xcoff"): + self = .xcoff + case let x where x.hasSuffix("coff"): + self = .coff + case let x where x.hasSuffix("elf"): + self = .elf + case let x where x.hasSuffix("macho"): + self = .machO + case let x where x.hasSuffix("wasm"): + self = .wasm + default: + self = .unknown + } + } + + /// Returns the default object file format for the given architecture and + /// operating system. + /// + /// - Parameters: + /// - arch: The architecture. + /// - os: The operatuing system. + /// - Returns: A default object file format compatible with the given + /// architecture and operating system. + public static func `default`(for arch: Architecture, os: OS) -> ObjectFormat { + switch arch { + case .unknown, .aarch64, .arm, .thumb, .x86, .x86_64: + if os.isDarwin { + return .machO + } else if os.isWindows { + return .coff + } + return .elf + + case .aarch64_be, .arc, .amdgcn, .amdil, .amdil64, .armeb, .avr, + .bpfeb, .bpfel, .hexagon, .lanai, .hsail, .hsail64, .kalimba, + .le32, .le64, .mips, .mips64, .mips64el, .mipsel, .msp430, + .nvptx, .nvptx64, .ppc64le, + .r600, .renderscript32, .renderscript64, .riscv32, .riscv64, + .shave, .sparc, .sparcel, .sparcv9, .spir, .spir64, .systemz, + .tce, .tcele, .thumbeb, .xcore: + return .elf + + case .ppc, .ppc64: + if os.isDarwin { + return .machO + } else if os.isAIX { + return .xcoff + } + return .elf + + case .wasm32, .wasm64: + return .wasm + } + } + } +} diff --git a/Sources/LLVM/Units.swift b/Sources/LLVM/Units.swift new file mode 100644 index 00000000..65ff0d47 --- /dev/null +++ b/Sources/LLVM/Units.swift @@ -0,0 +1,320 @@ +/// An alignment value, expressed in bytes. +public struct Alignment: Comparable, Hashable { + /// Accesses the raw alignment value in bytes. + /// + /// - warning: This accessor allows breaking out of the Alignment abstraction + /// for raw alignment calculations. It is therefore not recommended that + /// this accessor be used in user code. + public let rawValue: UInt32 + + /// A zero-byte alignment value. + public static let zero = Alignment(0) + /// An one-byte alignment value. + public static let one = Alignment(1) + + /// Initializes and returns an alignment with the given value interpreted as + /// a quantity of bytes. + public init(_ value: UInt32) { + self.rawValue = value + } + + /// Returns true if this alignment value is zero bytes, else return false. + public var isZero: Bool { + return self.rawValue == 0 + } + + /// Returns the value of this alignment in bits according to a given radix. + /// + /// - parameter radix: The radix value. Defaults to 8 bits per alignment unit. + /// - returns: A value in bits. + public func valueInBits(radix: UInt32 = 8) -> UInt32 { + return self.rawValue * radix + } + + /// Returns the log-base-two value of this alignment as a 32-bit integer. + /// + /// An n-byte alignment contains log-base-two-many least-significant zeros. + public func log2() -> UInt32 { + guard !isZero else { return 0 } + return 31 - UInt32(self.rawValue.leadingZeroBitCount) + } + + /// Returns the log-base-two value of this alignment as a 64-bit integer. + /// + /// An n-byte alignment contains log-base-two-many least-significant zeros. + public func log2() -> UInt64 { + guard !isZero else { return 0 } + // rawValue is only 32 bits + return 31 - UInt64(self.rawValue.leadingZeroBitCount) + } + + /// Returns the alignment of a pointer which points to the given number of + /// bytes after a pointer with this alignment. + public func alignment(at offset: Size) -> Alignment { + assert(self.rawValue != 0, "called on object with zero alignment") + + // If the offset is zero, use the original alignment. + var V = Int32(offset.rawValue) + guard V != 0 else { + return self + } + + // Find the offset's largest power-of-two factor. + V = V & -V + + // The alignment at the offset is then the min of the two values. + guard V < self.rawValue else { + return self + } + + return Alignment(UInt32(V)) + } + + public static func == (lhs: Alignment, rhs: Alignment) -> Bool { + return lhs.rawValue == rhs.rawValue + } + + public static func < (lhs: Alignment, rhs: Alignment) -> Bool { + return lhs.rawValue < rhs.rawValue + } + + public func hash(into hasher: inout Hasher) { + self.rawValue.hash(into: &hasher) + } +} + +/// This is an opaque type for sizes expressed in aggregate bit units, usually 8 +/// bits per unit. +/// +/// Instances of this type represent a quantity as a multiple of a radix size +/// - e.g. the size of a `char` in bits on the target architecture. As an opaque +/// type, `Size` protects you from accidentally combining operations on +/// quantities in bit units and size units. +/// +/// For portability, never assume that a target radix is 8 bits wide. Use +/// Size values wherever you calculate sizes and offsets. +public struct Size { + /// Accesses the raw value unitless value of this size. + /// + /// - warning: This accessor breaks the `Size` abstraction by allowing access + /// to the raw value. The underlying value is unitless and hence any + /// reinterpretation may lead to incorrect results in calculations that + /// depend on precise bit and byte-level arithmetic. This accessor should + /// not be used by user code in general. + public let rawValue: UInt64 + + /// A size carrying a value of zero. + public static let zero = Size(0) + /// A size carrying a value of one. + public static let one = Size(1) + + /// Initializes and returns a size carrying the given value. + public init(_ value: UInt64) { + self.rawValue = value + } + + /// Initializes and returns a size carrying the given value which represents + /// a value in bits with a given radix. + /// + /// - parameter bitSize: A given number of bits. + /// - parameter radix: The radix value. Defaults to 8 bits per size unit. + public init(bits bitSize: UInt64, radix: UInt64 = 8) { + precondition(radix > 0, "radix cannot be 0") + self.rawValue = (bitSize + (radix - 1)) / radix + } + + /// Returns the value of this size in bits according to a given radix. + /// + /// - parameter radix: The radix value. Defaults to 8 bits per size unit. + /// - returns: A value in bits. + public func valueInBits(radix: UInt64 = 8) -> UInt64 { + return self.rawValue * radix + } + + /// Returns true if this size value is a power of two, including if it is + /// zero. Returns false otherwise. + public var isPowerOfTwo: Bool { + return (self.rawValue != 0) + && ((self.rawValue & (self.rawValue - 1)) == 0) + } + + /// Computes a size with value rounded up to the next highest value that is + /// a multiple of the given alignment value. + /// + /// - parameter alignment: The alignment value. Must not be zero. + /// - returns: A size representing the given value rounded up to the given + /// alignment value. + public func roundUp(to alignment: Alignment) -> Size { + precondition(!alignment.isZero, "Cannot round up with zero alignment!") + let mask = UInt64(alignment.rawValue - 1) + let value = self.rawValue + mask + return Size(value & ~mask) + } + + /// Returns the remainder of dividing the first size value + /// by the second alignment value. This has the effect of aligning the + /// size value subtractively. + public static func % (lhs: Size, rhs: Alignment) -> Size { + return Size(lhs.rawValue % UInt64(rhs.rawValue)) + } +} + +extension Size: UnsignedInteger { + public init(clamping source: T) where T : BinaryInteger { + self.init(UInt64(clamping: source)) + } + + public init(truncatingIfNeeded source: T) where T : BinaryInteger { + self.init(UInt64(clamping: source)) + } + + public init?(exactly source: T) where T : BinaryInteger { + guard let val = UInt64(exactly: source) else { + return nil + } + self.init(val) + } + + public init(integerLiteral value: UInt64) { + self.init(value) + } + + public init?(exactly source: T) where T : BinaryFloatingPoint { + guard let val = UInt64(exactly: source) else { + return nil + } + self.init(val) + } + + public init(_ source: T) where T : BinaryFloatingPoint { + self.init(UInt64(source)) + } + + public init(_ source: T) where T : BinaryInteger { + self.init(UInt64(source)) + } + + public var words: UInt64.Words { + return self.rawValue.words + } + + public var bitWidth: Int { + return self.rawValue.bitWidth + } + + public var trailingZeroBitCount: Int { + return self.rawValue.trailingZeroBitCount + } + + public static func == (lhs: Size, rhs: Size) -> Bool { + return lhs.rawValue == rhs.rawValue + } + + public static func < (lhs: Size, rhs: Size) -> Bool { + return lhs.rawValue < rhs.rawValue + } + + + public func hash(into hasher: inout Hasher) { + self.rawValue.hash(into: &hasher) + } + + public static func + (lhs: Size, rhs: Size) -> Size { + var lhs = lhs + lhs += rhs + return lhs + } + public static func += (lhs: inout Size, rhs: Size) { + lhs = Size(lhs.rawValue + rhs.rawValue) + } + + public static func - (lhs: Size, rhs: Size) -> Size { + var lhs = lhs + lhs -= rhs + return lhs + } + public static func -= (lhs: inout Size, rhs: Size) { + lhs = Size(lhs.rawValue - rhs.rawValue) + } + + public static func * (lhs: Size, rhs: Size) -> Size { + var lhs = lhs + lhs *= rhs + return lhs + } + public static func *= (lhs: inout Size, rhs: Size) { + lhs = Size(lhs.rawValue * rhs.rawValue) + } + + public static func / (lhs: Size, rhs: Size) -> Size { + var lhs = lhs + lhs /= rhs + return lhs + } + public static func /= (lhs: inout Size, rhs: Size) { + lhs = Size(lhs.rawValue / rhs.rawValue) + } + + public static func % (lhs: Size, rhs: Size) -> Size { + var lhs = lhs + lhs %= rhs + return lhs + } + public static func %= (lhs: inout Size, rhs: Size) { + lhs = Size(lhs.rawValue % rhs.rawValue) + } + + public static func &= (lhs: inout Size, rhs: Size) { + lhs = Size(lhs.rawValue & rhs.rawValue) + } + + public static func |= (lhs: inout Size, rhs: Size) { + lhs = Size(lhs.rawValue | rhs.rawValue) + } + + public static func ^= (lhs: inout Size, rhs: Size) { + lhs = Size(lhs.rawValue ^ rhs.rawValue) + } + + public static func >>= (lhs: inout Size, rhs: RHS) { + lhs = Size(lhs.rawValue >> rhs) + } + + public static func <<= (lhs: inout Size, rhs: RHS) { + lhs = Size(lhs.rawValue << rhs) + } + + public static prefix func ~ (x: Size) -> Size { + return Size(~x.rawValue) + } + + /// Returns true if the given size is a multiple of this size. + public func isMultiple(of other: Size) -> Bool { + return (self.rawValue % other.rawValue) == 0 + } + + public typealias IntegerLiteralType = UInt64 + public typealias Words = UInt64.Words +} + +extension Size { + /// Multiplies a size value by a raw unitless value and produces their product. + public static func * (lhs: Size, rhs: UInt64) -> Size { + var lhs = lhs + lhs *= Size(rhs) + return lhs + } + + /// Multiplies a raw unitless value by a size value and produces their product. + public static func * (lhs: UInt64, rhs: Size) -> Size { + var lhs = Size(lhs) + lhs *= rhs + return lhs + } + + /// Multiplies a size value by a raw unitless value and stores the result in + /// the left-hand-side size variable. + public static func *= (lhs: inout Size, rhs: UInt64) { + lhs = Size(lhs.rawValue * rhs) + } +} diff --git a/Sources/LLVM/VectorType.swift b/Sources/LLVM/VectorType.swift index e73dbfd8..a502a19e 100644 --- a/Sources/LLVM/VectorType.swift +++ b/Sources/LLVM/VectorType.swift @@ -44,3 +44,9 @@ public struct VectorType: IRType { return LLVMVectorType(elementType.asLLVM(), UInt32(count)) } } + +extension VectorType: Equatable { + public static func == (lhs: VectorType, rhs: VectorType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() + } +} diff --git a/Sources/LLVM/VoidType.swift b/Sources/LLVM/VoidType.swift index ee395559..806cf2fd 100644 --- a/Sources/LLVM/VoidType.swift +++ b/Sources/LLVM/VoidType.swift @@ -21,3 +21,9 @@ public struct VoidType: IRType { return LLVMVoidTypeInContext(context.llvm) } } + +extension VoidType: Equatable { + public static func == (lhs: VoidType, rhs: VoidType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() + } +} diff --git a/Sources/LLVM/X86MMXType.swift b/Sources/LLVM/X86MMXType.swift index 4136e689..1078d48e 100644 --- a/Sources/LLVM/X86MMXType.swift +++ b/Sources/LLVM/X86MMXType.swift @@ -26,3 +26,9 @@ public struct X86MMXType: IRType { return LLVMX86MMXTypeInContext(context.llvm) } } + +extension X86MMXType: Equatable { + public static func == (lhs: X86MMXType, rhs: X86MMXType) -> Bool { + return lhs.asLLVM() == rhs.asLLVM() + } +} diff --git a/Sources/cllvm/module.modulemap b/Sources/cllvm/module.modulemap new file mode 100644 index 00000000..3c70771d --- /dev/null +++ b/Sources/cllvm/module.modulemap @@ -0,0 +1,4 @@ +module cllvm [system] { + header "shim.h" + export * +} diff --git a/Sources/cllvm/shim.h b/Sources/cllvm/shim.h new file mode 100644 index 00000000..34606ac0 --- /dev/null +++ b/Sources/cllvm/shim.h @@ -0,0 +1,30 @@ +#define _GNU_SOURCE +#define __STDC_CONSTANT_MACROS +#define __STDC_FORMAT_MACROS +#define __STDC_LIMIT_MACROS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/Sources/llvmshims/include/shim.h b/Sources/llvmshims/include/shim.h new file mode 100644 index 00000000..30b5648e --- /dev/null +++ b/Sources/llvmshims/include/shim.h @@ -0,0 +1,36 @@ +#include +#include "llvm-c/Types.h" +#include "llvm-c/Object.h" +#include "llvm-c/DebugInfo.h" + +#ifndef LLVMSWIFT_LLVM_SHIM_H +#define LLVMSWIFT_LLVM_SHIM_H + +size_t LLVMSwiftCountIntrinsics(void); +const char *LLVMSwiftGetIntrinsicAtIndex(size_t index); +const char *LLVMGetARMCanonicalArchName(const char *Name, size_t NameLen); + +typedef enum { + LLVMARMProfileKindInvalid = 0, + LLVMARMProfileKindA, + LLVMARMProfileKindR, + LLVMARMProfileKindM +} LLVMARMProfileKind; +LLVMARMProfileKind LLVMARMParseArchProfile(const char *Name, size_t NameLen); +unsigned LLVMARMParseArchVersion(const char *Name, size_t NameLen); + +uint64_t LLVMGlobalGetGUID(LLVMValueRef Global); + +void LLVMAddGlobalsAAWrapperPass(LLVMPassManagerRef PM); + +typedef enum { + LLVMTailCallKindNone, + LLVMTailCallKindTail, + LLVMTailCallKindMustTail, + LLVMTailCallKindNoTail +} LLVMTailCallKind; + +LLVMTailCallKind LLVMGetTailCallKind(LLVMValueRef CallInst); +void LLVMSetTailCallKind(LLVMValueRef CallInst, LLVMTailCallKind TCK); + +#endif /* LLVMSWIFT_LLVM_SHIM_H */ diff --git a/Sources/llvmshims/src/shim.cpp b/Sources/llvmshims/src/shim.cpp new file mode 100644 index 00000000..766d7b7e --- /dev/null +++ b/Sources/llvmshims/src/shim.cpp @@ -0,0 +1,118 @@ +#include "llvm-c/Core.h" +#include "llvm-c/Object.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/GlobalsModRef.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Object/MachOUniversal.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/ARMTargetParser.h" +#include "llvm/Transforms/Utils.h" +#include "llvm/Transforms/IPO.h" + +extern "C" { + // Not to be upstreamed: They support the hacks that power our dynamic member + // lookup machinery for intrinsics. + const char *LLVMSwiftGetIntrinsicAtIndex(size_t index); + size_t LLVMSwiftCountIntrinsics(void); + + // Not to be upstreamed: There's no value in this without a full Triple + // API. And we have chosen to port instead of wrap. + const char *LLVMGetARMCanonicalArchName(const char *Name, size_t NameLen); + + typedef enum { + LLVMARMProfileKindInvalid = 0, + LLVMARMProfileKindA, + LLVMARMProfileKindR, + LLVMARMProfileKindM + } LLVMARMProfileKind; + + LLVMARMProfileKind LLVMARMParseArchProfile(const char *Name, size_t NameLen); + unsigned LLVMARMParseArchVersion(const char *Name, size_t NameLen); + + // Not to be upstreamed: It's not clear there's value in having this outside + // of PGO passes. + uint64_t LLVMGlobalGetGUID(LLVMValueRef Global); + + // https://reviews.llvm.org/D66237 + void LLVMAddGlobalsAAWrapperPass(LLVMPassManagerRef PM); + + // https://reviews.llvm.org/D66061 + typedef enum { + LLVMTailCallKindNone, + LLVMTailCallKindTail, + LLVMTailCallKindMustTail, + LLVMTailCallKindNoTail + } LLVMTailCallKind; + + LLVMTailCallKind LLVMGetTailCallKind(LLVMValueRef CallInst); + void LLVMSetTailCallKind(LLVMValueRef CallInst, LLVMTailCallKind TCK); +} + +using namespace llvm; +using namespace llvm::object; + +size_t LLVMSwiftCountIntrinsics(void) { + return llvm::Intrinsic::num_intrinsics; +} + +const char *LLVMSwiftGetIntrinsicAtIndex(size_t index) { + return llvm::Intrinsic::getName(static_cast(index)).data(); +} + +LLVMARMProfileKind LLVMARMParseArchProfile(const char *Name, size_t NameLen) { + return static_cast(llvm::ARM::parseArchProfile({Name, NameLen})); +} + +unsigned LLVMARMParseArchVersion(const char *Name, size_t NameLen) { + return llvm::ARM::parseArchVersion({Name, NameLen}); +} + +const char *LLVMGetARMCanonicalArchName(const char *Name, size_t NameLen) { + return llvm::ARM::getCanonicalArchName({Name, NameLen}).data(); +} + +uint64_t LLVMGlobalGetGUID(LLVMValueRef Glob) { + return unwrap(Glob)->getGUID(); +} + +void LLVMAddGlobalsAAWrapperPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createGlobalsAAWrapperPass()); +} + +LLVMTailCallKind LLVMGetTailCallKind(LLVMValueRef Call) { + switch (unwrap(Call)->getTailCallKind()) { + case CallInst::TailCallKind::TCK_None: + return LLVMTailCallKindNone; + case CallInst::TailCallKind::TCK_Tail: + return LLVMTailCallKindTail; + case CallInst::TailCallKind::TCK_MustTail: + return LLVMTailCallKindMustTail; + case CallInst::TailCallKind::TCK_NoTail: + return LLVMTailCallKindNoTail; + } +} + +void LLVMSetTailCallKind(LLVMValueRef Call, LLVMTailCallKind TCK) { + CallInst::TailCallKind kind; + switch (TCK) { + case LLVMTailCallKindNone: + kind = CallInst::TailCallKind::TCK_None; + break; + case LLVMTailCallKindTail: + kind = CallInst::TailCallKind::TCK_Tail; + break; + case LLVMTailCallKindMustTail: + kind = CallInst::TailCallKind::TCK_MustTail; + break; + case LLVMTailCallKindNoTail: + kind = CallInst::TailCallKind::TCK_NoTail; + break; + } + + unwrap(Call)->setTailCallKind(kind); +} diff --git a/Tests/LLVMTests/APIntSpec.swift b/Tests/LLVMTests/APIntSpec.swift new file mode 100644 index 00000000..4224a2b5 --- /dev/null +++ b/Tests/LLVMTests/APIntSpec.swift @@ -0,0 +1,317 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +class APIntSpec : XCTestCase { + func testZeroInit() { + let zero = APInt() + XCTAssert(zero == APInt(width: 1, value: 0)) + XCTAssert(zero.zeroExtend(to: 64) == APInt(width: 64, value: 0)) + XCTAssert(zero.signExtend(to: 64) == APInt(width: 64, value: 0)) + } + + func testNegativeCount() { + let minus1 = APInt(width: 128, value: UInt64(bitPattern: -1), signed: true) + XCTAssertEqual(0, minus1.leadingZeroBitCount) + XCTAssertEqual(0, minus1.trailingZeroBitCount) + XCTAssertEqual(128, minus1.nonzeroBitCount) + } + + func testi33Count() { + let i33minus2 = APInt(width: 33, value: UInt64(bitPattern: -2), signed: true) + XCTAssertEqual(0, i33minus2.leadingZeroBitCount) + XCTAssertEqual(1, i33minus2.trailingZeroBitCount) + XCTAssertEqual(32, i33minus2.nonzeroBitCount) + } + + func testi61Count() { + let i61 = APInt(width: 61, value: 1 << 15) + XCTAssertEqual(45, i61.leadingZeroBitCount) + XCTAssertEqual(15, i61.trailingZeroBitCount) + XCTAssertEqual(1, i61.nonzeroBitCount) + } + + func testi65Count() { + let i65 = APInt(width: 65, value: 0, signed: true) + + XCTAssertEqual(65, i65.leadingZeroBitCount) + XCTAssertEqual(65, i65.trailingZeroBitCount) + XCTAssertEqual(0, i65.nonzeroBitCount) + } + + func testi1() { + let negTwo = APInt(width: 1, value: UInt64(bitPattern: -2), signed: true) + let negOne = APInt(width: 1, value: UInt64(bitPattern: -1), signed: true) + let zero = APInt(width: 1, value: 0) + let one = APInt(width: 1, value: 1) + let two = APInt(width: 1, value: 2) + + XCTAssertEqual(0, negTwo.signExtendedValue!) + XCTAssertEqual(-1, negOne.signExtendedValue!) + XCTAssertEqual(1, negOne.zeroExtendedValue!) + XCTAssertEqual(0, zero.zeroExtendedValue!) + XCTAssertEqual(-1, one.signExtendedValue!) + XCTAssertEqual(1, one.zeroExtendedValue!) + XCTAssertEqual(0, two.zeroExtendedValue!) + XCTAssertEqual(0, two.signExtendedValue!) + + // Basic equalities for 1-bit values. + XCTAssertEqual(zero, two) + XCTAssertEqual(zero, negTwo) + XCTAssertEqual(one, negOne) + XCTAssertEqual(two, negTwo) + + // Additions. + XCTAssertEqual(two, one + one) + XCTAssertEqual(zero, negOne + one) + XCTAssertEqual(negTwo, negOne + negOne) + + // Subtractions. + XCTAssertEqual(negTwo, negOne - one) + XCTAssertEqual(two, one - negOne) + XCTAssertEqual(zero, one - one) + + // And + XCTAssertEqual(zero, zero & zero) + XCTAssertEqual(zero, one & zero) + XCTAssertEqual(zero, zero & one) + XCTAssertEqual(one, one & one) + XCTAssertEqual(zero, zero & zero) + XCTAssertEqual(zero, negOne & zero) + XCTAssertEqual(zero, zero & negOne) + XCTAssertEqual(negOne, negOne & negOne) + + // Or + XCTAssertEqual(zero, zero | zero) + XCTAssertEqual(one, one | zero) + XCTAssertEqual(one, zero | one) + XCTAssertEqual(one, one | one) + XCTAssertEqual(zero, zero | zero) + XCTAssertEqual(negOne, negOne | zero) + XCTAssertEqual(negOne, zero | negOne) + XCTAssertEqual(negOne, negOne | negOne) + + // Xor + XCTAssertEqual(zero, zero ^ zero) + XCTAssertEqual(one, one ^ zero) + XCTAssertEqual(one, zero ^ one) + XCTAssertEqual(zero, one ^ one) + XCTAssertEqual(zero, zero ^ zero) + XCTAssertEqual(negOne, negOne ^ zero) + XCTAssertEqual(negOne, zero ^ negOne) + XCTAssertEqual(zero, negOne ^ negOne) + + // Shifts. + XCTAssertEqual(zero, one << 1) + XCTAssertEqual(one, one << 0) + XCTAssertEqual(zero, one.logicallyShiftedRight(by: 1)) + + // Multiplies. + XCTAssertEqual(negOne, negOne * one) + XCTAssertEqual(negOne, one * negOne) + XCTAssertEqual(one, negOne * negOne) + XCTAssertEqual(one, one * one) + } + + func testMultiply() { + let i64 = APInt(width: 64, value: 1234) + + XCTAssertEqual(7006652, i64 * 5678) + XCTAssertEqual(7006652, 5678 * i64) + + let i128 = APInt(width: 128, value: 1 << 64) + var i128_1234 = APInt(width: 128, value: 1234) + i128_1234 <<= 64 + XCTAssertEqual(i128_1234, i128 * APInt(width: 128, value: 1234)) + XCTAssertEqual(i128_1234, APInt(width: 128, value: 1234) * i128) + + var i96 = APInt(width: 96, value: 1 << 64) + i96 *= APInt(width: 96, value: UInt64.max) + XCTAssertEqual(96, i96.leadingZeroBitCount) + XCTAssertEqual(0, i96.nonzeroBitCount) + XCTAssertEqual(96, i96.trailingZeroBitCount) + } + + func testSetLowBits() { + var i64lo32 = APInt(width: 64, value: 0) + i64lo32.setBits(...32) + XCTAssertEqual(0, i64lo32.leadingNonZeroBitCount) + XCTAssertEqual(32, i64lo32.leadingZeroBitCount) + XCTAssertEqual(0, i64lo32.trailingZeroBitCount) + XCTAssertEqual(32, i64lo32.trailingNonZeroBitCount) + XCTAssertEqual(32, i64lo32.nonzeroBitCount) + + var i128lo64 = APInt(width: 128, value: 0) + i128lo64.setBits(...64) + XCTAssertEqual(0, i128lo64.leadingNonZeroBitCount) + XCTAssertEqual(64, i128lo64.leadingZeroBitCount) + XCTAssertEqual(0, i128lo64.trailingZeroBitCount) + XCTAssertEqual(64, i128lo64.trailingNonZeroBitCount) + XCTAssertEqual(64, i128lo64.nonzeroBitCount) + + var i128lo24 = APInt(width: 128, value: 0) + i128lo24.setBits(...24) + XCTAssertEqual(0, i128lo24.leadingNonZeroBitCount) + XCTAssertEqual(104, i128lo24.leadingZeroBitCount) + XCTAssertEqual(0, i128lo24.trailingZeroBitCount) + XCTAssertEqual(24, i128lo24.trailingNonZeroBitCount) + XCTAssertEqual(24, i128lo24.nonzeroBitCount) + + var i128lo104 = APInt(width: 128, value: 0) + i128lo104.setBits(...104) + XCTAssertEqual(0, i128lo104.leadingNonZeroBitCount) + XCTAssertEqual(24, i128lo104.leadingZeroBitCount) + XCTAssertEqual(0, i128lo104.trailingZeroBitCount) + XCTAssertEqual(104, i128lo104.trailingNonZeroBitCount) + XCTAssertEqual(104, i128lo104.nonzeroBitCount) + + var i128lo0 = APInt(width: 128, value: 0) + i128lo0.setBits(...0) + XCTAssertEqual(0, i128lo0.leadingNonZeroBitCount) + XCTAssertEqual(128, i128lo0.leadingZeroBitCount) + XCTAssertEqual(128, i128lo0.trailingZeroBitCount) + XCTAssertEqual(0, i128lo0.trailingNonZeroBitCount) + XCTAssertEqual(0, i128lo0.nonzeroBitCount) + + var i80lo79 = APInt(width: 80, value: 0) + i80lo79.setBits(...79) + XCTAssertEqual(0, i80lo79.leadingNonZeroBitCount) + XCTAssertEqual(1, i80lo79.leadingZeroBitCount) + XCTAssertEqual(0, i80lo79.trailingZeroBitCount) + XCTAssertEqual(79, i80lo79.trailingNonZeroBitCount) + XCTAssertEqual(79, i80lo79.nonzeroBitCount) + } + + func testSetHighBits() { + var i64hi32 = APInt(width: 64, value: 0) + i64hi32.setBits((i64hi32.bitWidth - 32)...) + XCTAssertEqual(32, i64hi32.leadingNonZeroBitCount) + XCTAssertEqual(0, i64hi32.leadingZeroBitCount) + XCTAssertEqual(32, i64hi32.trailingZeroBitCount) + XCTAssertEqual(0, i64hi32.trailingNonZeroBitCount) + XCTAssertEqual(32, i64hi32.nonzeroBitCount) + + var i128hi64 = APInt(width: 128, value: 0) + i128hi64.setBits((i128hi64.bitWidth - 64)...) + XCTAssertEqual(64, i128hi64.leadingNonZeroBitCount) + XCTAssertEqual(0, i128hi64.leadingZeroBitCount) + XCTAssertEqual(64, i128hi64.trailingZeroBitCount) + XCTAssertEqual(0, i128hi64.trailingNonZeroBitCount) + XCTAssertEqual(64, i128hi64.nonzeroBitCount) + + var i128hi24 = APInt(width: 128, value: 0) + i128hi24.setBits((i128hi24.bitWidth - 24)...) + XCTAssertEqual(24, i128hi24.leadingNonZeroBitCount) + XCTAssertEqual(0, i128hi24.leadingZeroBitCount) + XCTAssertEqual(104, i128hi24.trailingZeroBitCount) + XCTAssertEqual(0, i128hi24.trailingNonZeroBitCount) + XCTAssertEqual(24, i128hi24.nonzeroBitCount) + + var i128hi104 = APInt(width: 128, value: 0) + i128hi104.setBits((i128hi104.bitWidth - 104)...) + XCTAssertEqual(104, i128hi104.leadingNonZeroBitCount) + XCTAssertEqual(0, i128hi104.leadingZeroBitCount) + XCTAssertEqual(24, i128hi104.trailingZeroBitCount) + XCTAssertEqual(0, i128hi104.trailingNonZeroBitCount) + XCTAssertEqual(104, i128hi104.nonzeroBitCount) + + var i128hi0 = APInt(width: 128, value: 0) + i128hi0.setBits((i128hi0.bitWidth - 0)...) + XCTAssertEqual(0, i128hi0.leadingNonZeroBitCount) + XCTAssertEqual(128, i128hi0.leadingZeroBitCount) + XCTAssertEqual(128, i128hi0.trailingZeroBitCount) + XCTAssertEqual(0, i128hi0.trailingNonZeroBitCount) + XCTAssertEqual(0, i128hi0.nonzeroBitCount) + + var i80hi1 = APInt(width: 80, value: 0) + i80hi1.setBits((i80hi1.bitWidth - 1)...) + XCTAssertEqual(1, i80hi1.leadingNonZeroBitCount) + XCTAssertEqual(0, i80hi1.leadingZeroBitCount) + XCTAssertEqual(79, i80hi1.trailingZeroBitCount) + XCTAssertEqual(0, i80hi1.trailingNonZeroBitCount) + XCTAssertEqual(1, i80hi1.nonzeroBitCount) + + var i32hi16 = APInt(width: 32, value: 0) + i32hi16.setBits((i32hi16.bitWidth - 16)...) + XCTAssertEqual(16, i32hi16.leadingNonZeroBitCount) + XCTAssertEqual(0, i32hi16.leadingZeroBitCount) + XCTAssertEqual(16, i32hi16.trailingZeroBitCount) + XCTAssertEqual(0, i32hi16.trailingNonZeroBitCount) + XCTAssertEqual(16, i32hi16.nonzeroBitCount) + } + + func testSetBitsFrom() { + var i64from63 = APInt(width: 64, value: 0) + i64from63.setBits(63...) + XCTAssertEqual(1, i64from63.leadingNonZeroBitCount) + XCTAssertEqual(0, i64from63.leadingZeroBitCount) + XCTAssertEqual(63, i64from63.trailingZeroBitCount) + XCTAssertEqual(0, i64from63.trailingNonZeroBitCount) + XCTAssertEqual(1, i64from63.nonzeroBitCount) + } + + func testSetAllBits() { + var i32 = APInt(width: 32, value: 0) + i32.setAllBits() + XCTAssertEqual(32, i32.leadingNonZeroBitCount) + XCTAssertEqual(0, i32.leadingZeroBitCount) + XCTAssertEqual(0, i32.trailingZeroBitCount) + XCTAssertEqual(32, i32.trailingNonZeroBitCount) + XCTAssertEqual(32, i32.nonzeroBitCount) + + var i64 = APInt(width: 64, value: 0) + i64.setAllBits() + XCTAssertEqual(64, i64.leadingNonZeroBitCount) + XCTAssertEqual(0, i64.leadingZeroBitCount) + XCTAssertEqual(0, i64.trailingZeroBitCount) + XCTAssertEqual(64, i64.trailingNonZeroBitCount) + XCTAssertEqual(64, i64.nonzeroBitCount) + + var i96 = APInt(width: 96, value: 0) + i96.setAllBits() + XCTAssertEqual(96, i96.leadingNonZeroBitCount) + XCTAssertEqual(0, i96.leadingZeroBitCount) + XCTAssertEqual(0, i96.trailingZeroBitCount) + XCTAssertEqual(96, i96.trailingNonZeroBitCount) + XCTAssertEqual(96, i96.nonzeroBitCount) + + var i128 = APInt(width: 128, value: 0) + i128.setAllBits() + XCTAssertEqual(128, i128.leadingNonZeroBitCount) + XCTAssertEqual(0, i128.leadingZeroBitCount) + XCTAssertEqual(0, i128.trailingZeroBitCount) + XCTAssertEqual(128, i128.trailingNonZeroBitCount) + XCTAssertEqual(128, i128.nonzeroBitCount) + } + + func testArbitraryIRGen() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["ARBITRARY"]) { + // ARBITRARY: ModuleID = '[[ModuleName:ArbitraryTest]]' + // ARBITRARY-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "ArbitraryTest") + let builder = IRBuilder(module: module) + let intType = IntType(width: 420) + // ARBITRARY: define i420 @test() { + let main = builder.addFunction("test", + type: FunctionType([], intType)) + // ARBITRARY-NEXT: entry: + let entry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + // ARBITRARY-NEXT: ret i420 420 + builder.buildRet(APInt(width: 420, value: 0b00000001_10100100)) + // ARBITRARY-NEXT: } + module.dump() + }) + } + + #if !os(macOS) + static var allTests = testCase([ + ("testZeroInit", testZeroInit), + ("testi33Count", testi33Count), + ("testi1", testi1), + ("testMultiply", testMultiply), + ("testArbitraryIRGen", testArbitraryIRGen), + ]) + #endif +} diff --git a/Tests/LLVMTests/BFC.swift b/Tests/LLVMTests/BFC.swift new file mode 100644 index 00000000..33eba158 --- /dev/null +++ b/Tests/LLVMTests/BFC.swift @@ -0,0 +1,419 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +class BFCSpec : XCTestCase { + func testCompile() { + // So, this looks weird for a reason. It has to be edge-aligned because + // I'm lazy and didn't want to implement column resets correctly. And it has + // to be indented on every operation because LLVM de-duplicates source + // locations by file and line. So even if you emit two distinct locations + // for two distinct operations on the same line, you'll step over both of + // them if they don't have discriminators set. We need hooks for this. + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["BFC"]) { + // BFC: ; ModuleID = 'brainfuck' +compile( +""" ++ ++ ++ ++ ++ ++ ++ ++ +[ +> ++ ++ ++ ++ +[ +> ++ ++ +> ++ ++ ++ +> ++ ++ ++ +> ++ +< +< +< +< +- +] +> ++ +> ++ +> +- +> +> ++ +[ +< +] +< +- +] +> +> +. +> +- +- +- +. ++ ++ ++ ++ ++ ++ ++ +. +. ++ ++ ++ +. +> +> +. +< +- +. +< +. ++ ++ ++ +. +- +- +- +- +- +- +. +- +- +- +- +- +- +- +- +. +> +> ++ +. +> ++ ++ +. +""") + }) + } + #if !os(macOS) + static var allTests = testCase([ + ("testCompile", testCompile) + ]) + #endif +} + +private let cellType = IntType.int8 +private let cellTapeType = ArrayType(elementType: cellType, count: 30000) + +struct Loop { + let entry: BasicBlock + let body: BasicBlock + let exit: BasicBlock + let headerDestination: PhiNode + let exitDestination: PhiNode +} + +private enum Externs { + case putchar + case getchar + case flush + + func resolve(_ builder: IRBuilder) -> Function { + let lastEntry = builder.insertBlock + defer { if let pos = lastEntry { builder.positionAtEnd(of: pos) } } + switch self { + case .getchar: + let f = builder.addFunction("readchar", + type: FunctionType([], + cellType)) + let getCharExtern = builder.addFunction("getchar", + type: FunctionType([], + cellType)) + let entry = f.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + let charValue = builder.buildCall(getCharExtern, args: []) + let cond = builder.buildICmp(charValue, cellType.constant(0), .signedGreaterThanOrEqual) + let retVal = builder.buildSelect(cond, then: charValue, else: cellType.constant(0)) + builder.buildRet(retVal) + return f + case .putchar: + return builder.addFunction("putchar", + type: FunctionType([ + cellType + ], VoidType())) + case .flush: + let f = builder.addFunction("flush", + type: FunctionType([], VoidType())) + let entry = f.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + let ptrTy = PointerType(pointee: IntType.int8) + let fflushExtern = builder.addFunction("fflush", + type: FunctionType([ ptrTy ], + IntType.int32)) + _ = builder.buildCall(fflushExtern, args: [ ptrTy.constPointerNull() ]) + builder.buildRetVoid() + return f + } + } +} + +private func compile(at column: Int = #column, line: Int = #line, _ program: String) { + let module = Module(name: "brainfuck") + let builder = IRBuilder(module: module) + let dibuilder = DIBuilder(module: module) + let cellTape = module.addGlobal("tape", initializer: cellTapeType.null()) + + let main = builder.addFunction("main", + type: FunctionType([], + IntType.int32)) + + let sourceFile = #file.components(separatedBy: "/").last! + let sourceDir = #file.components(separatedBy: "/").dropLast().joined(separator: "/") + let mainFile = dibuilder.buildFile(named: sourceFile, + in: sourceDir) + let compileUnit = dibuilder.buildCompileUnit(for: .c, in: mainFile, kind: .full) + let mainModule = dibuilder.buildModule( + named: "bf", scope: compileUnit, macros: [], + includePath: sourceDir, includeSystemRoot: "") + _ = dibuilder.buildImportedModule( + in: mainFile, module: mainModule, file: mainFile, line: 0) + + let diFnTy = dibuilder.buildSubroutineType(in: mainFile, parameterTypes: []) + main.metadata = dibuilder.buildFunction( + named: "main", linkageName: "_main", scope: mainFile, + file: mainFile, line: line, scopeLine: line, + type: diFnTy, flags: [], isLocal: true) + + let entryBlock = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entryBlock) + + let mainScope = dibuilder.buildLexicalBlock( + scope: main.metadata, file: mainFile, line: line, column: column) + + compileProgramBody(program, (line, column), builder, dibuilder, main, mainScope, mainFile, cellTape) + + dibuilder.finalize() + + module.dump() + + /* Uncomment to output an object file. + let targetMachine = try! TargetMachine(optLevel: .none) + try! targetMachine.emitToFile(module: module, type: .object, path: sourceDir + "/bf.o") + */ +} + +private func compileProgramBody( + _ program: String, + _ startPoint: (Int, Int), + _ builder: IRBuilder, + _ dibuilder: DIBuilder, + _ function: Function, + _ entryScope: DIScope, + _ file: FileMetadata, + _ cellTape: Global +) { + + let putCharExtern = Externs.putchar.resolve(builder) + let getCharExtern = Externs.getchar.resolve(builder) + let flushExtern = Externs.flush.resolve(builder) + + var addressPointer: IRValue = cellTape.constGEP(indices: [ + IntType.int32.zero(), // (*self) + IntType.int32.zero() // [0] + ]) + + /// Create an artificial typedef and variable for the current + /// pointer into the tape. + /// + /// typedef long value_t; + /// + /// value_t this = 0; + let diDataTy = dibuilder.buildBasicType(named: "value_t", + encoding: .signed, flags: [], + size: builder.module.dataLayout.abiSize(of: cellType)) + let diPtrTy = dibuilder.buildPointerType(pointee: diDataTy, + size: builder.module.dataLayout.pointerSize(), + alignment: .one) + let diVariable = dibuilder.buildLocalVariable(named: "this", + scope: entryScope, + file: file, line: startPoint.0, + type: diPtrTy, flags: .artificial, + alignment: .one) + + var sourceLine = startPoint.0 + 1 + var sourceColumn = startPoint.1 + 1 + + // Declare the variable at the start of the function and give it a value of 0. + let loc = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: entryScope) + dibuilder.buildDeclare(of: addressPointer, atEndOf: builder.insertBlock!, + metadata: diVariable, + expr: dibuilder.buildExpression([]), + location: loc) + dibuilder.buildDbgValue(of: cellType.zero(), to: diVariable, + atEndOf: builder.insertBlock!, + expr: dibuilder.buildExpression([]), + location: loc) + + var loopNest = [Loop]() + var scopeStack = [DIScope]() + scopeStack.append(entryScope) + + for c in program { + sourceColumn += 1 + let scope = scopeStack.last! + switch c { + case ">": + // Move right + addressPointer = builder.buildGEP(addressPointer, type: cellTapeType, indices: [ IntType.int32.constant(1) ]) + builder.currentDebugLocation = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: scope) + dibuilder.buildDbgValue(of: addressPointer, to: diVariable, + atEndOf: builder.insertBlock!, + expr: dibuilder.buildExpression([.deref]), + location: builder.currentDebugLocation!) + case "<": + // Move left + addressPointer = builder.buildGEP(addressPointer, type: cellTapeType, indices: [ IntType.int32.constant(-1) ]) + builder.currentDebugLocation = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: scope) + dibuilder.buildDbgValue(of: addressPointer, to: diVariable, + atEndOf: builder.insertBlock!, + expr: dibuilder.buildExpression([.deref]), + location: builder.currentDebugLocation!) + case "+": + // Increment + let value = builder.buildLoad(addressPointer, type: cellType) + let ptrUp = builder.buildAdd(value, cellType.constant(1)) + builder.buildStore(ptrUp, to: addressPointer) + builder.currentDebugLocation = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: scope) + dibuilder.buildDbgValue(of: value, to: diVariable, + atEndOf: builder.insertBlock!, + expr: dibuilder.buildExpression([.plus_uconst(1)]), + location: builder.currentDebugLocation!) + case "-": + // Decrement + let value = builder.buildLoad(addressPointer, type: cellType) + let ptrDown = builder.buildSub(value, cellType.constant(1)) + builder.buildStore(ptrDown, to: addressPointer) + builder.currentDebugLocation = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: scope) + dibuilder.buildDbgValue(of: value, to: diVariable, + atEndOf: builder.insertBlock!, + expr: dibuilder.buildExpression([.constu(1), .minus]), + location: builder.currentDebugLocation!) + case ".": + // Write + let dataValue = builder.buildLoad(addressPointer, type: cellType) + _ = builder.buildCall(putCharExtern, args: [dataValue]) + builder.currentDebugLocation = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: scope) + case ",": + // Read + let readValue = builder.buildCall(getCharExtern, args: []) + builder.buildStore(readValue, to: addressPointer) + builder.currentDebugLocation = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: scope) + + case "[": + // Jump If Zero + let loopEntry = builder.insertBlock! + let loopBody = function.appendBasicBlock(named: "loop") + let loopExit = function.appendBasicBlock(named: "exit") + + // If zero + let cond = builder.buildIsNotNull(builder.buildLoad(addressPointer, type: cellType)) + builder.buildCondBr(condition: cond, then: loopBody, else: loopExit) + + // Build a PHI for any address pointer changes in the exit block. + builder.positionAtEnd(of: loopExit) + let exitDestPHI = builder.buildPhi(addressPointer.type) + exitDestPHI.addIncoming([ (addressPointer, loopEntry) ]) + + // Build a PHI for any address pointer changes in the loop body. + builder.positionAtEnd(of: loopBody) + let headerDestPHI = builder.buildPhi(addressPointer.type) + headerDestPHI.addIncoming([ (addressPointer, loopEntry) ]) + + // Build a lexical scope and enter it. + let loopScope = dibuilder.buildLexicalBlock( + scope: scope, file: file, + line: sourceLine, column: sourceColumn) + scopeStack.append(loopScope) + + // Move to the loop header. + addressPointer = headerDestPHI + + // Push the loop onto the nest. + loopNest.append(Loop(entry: loopEntry, + body: loopBody, + exit: loopExit, + headerDestination: headerDestPHI, + exitDestination: exitDestPHI)) + case "]": + // Jump If Not Zero + + // Pop the innermost loop off the nest. + guard let loop = loopNest.popLast() else { + fatalError("] requires matching [") + } + + // Exit the loop's scope + _ = scopeStack.popLast() + + // Finish off the phi nodes. + loop.headerDestination.addIncoming([ (addressPointer, builder.insertBlock!) ]) + loop.exitDestination.addIncoming([ (addressPointer, builder.insertBlock!) ]) + + // If not zero. + let cond = builder.buildIsNotNull(builder.buildLoad(addressPointer, type: cellType)) + builder.buildCondBr(condition: cond, then: loop.body, else: loop.exit) + + // Move the exit block after the loop body. + loop.exit.moveAfter(builder.insertBlock!) + + // Move to the exit. + addressPointer = loop.exitDestination + + builder.positionAtEnd(of: loop.exit) + case "\n": + sourceLine += 1 + sourceColumn = 1 + default: + continue + } + } + + // Ensure all loops have been closed. + guard loopNest.isEmpty && scopeStack.count == 1 else { + fatalError("[ requires matching ]") + } + + // Flush everything + _ = builder.buildCall(flushExtern, args: []) + + builder.buildRet(IntType.int32.zero()) +} diff --git a/Tests/LLVMTests/BinarySpec.swift b/Tests/LLVMTests/BinarySpec.swift new file mode 100644 index 00000000..a46d626c --- /dev/null +++ b/Tests/LLVMTests/BinarySpec.swift @@ -0,0 +1,51 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +class BinarySpec : XCTestCase { + private func readThisObjectFile() -> ObjectFile { + let result = Result(catching: { + try MachOUniversalBinaryFile(path: Bundle.main.executablePath!) + }) + switch result { + case .failure(_): + guard let objectFile = try? ObjectFile(path: Bundle.main.executablePath!) else { + fatalError("Missing object file for host architecture?") + } + return objectFile + case let .success(binary): + guard let objectFile = try? binary.objectFile(for: Triple.default.architecture) else { + fatalError("Missing object file for host architecture?") + } + return objectFile + } + } + + func testBinaryLifetimes() { + let objectFile = self.readThisObjectFile() + + #if !os(Linux) // Linux has some trouble reading ELF sections. + var hasSections = false + for _ in objectFile.sections { + hasSections = true + break + } + XCTAssertTrue(hasSections) + #endif + + var hasSymbols = false + for _ in objectFile.symbols { + hasSymbols = true + break + } + XCTAssertTrue(hasSymbols) + } + + #if !os(macOS) + static var allTests = testCase([ + ("testBinaryLifetimes", testBinaryLifetimes), + ]) + #endif +} + diff --git a/Tests/LLVMTests/ConstantSpec.swift b/Tests/LLVMTests/ConstantSpec.swift index f586b9c0..72857295 100644 --- a/Tests/LLVMTests/ConstantSpec.swift +++ b/Tests/LLVMTests/ConstantSpec.swift @@ -12,8 +12,7 @@ class ConstantSpec : XCTestCase { let builder = IRBuilder(module: module) // SIGNEDCONST: define void @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: VoidType())) + type: FunctionType([], VoidType())) let constant = IntType.int64.constant(42) // SIGNEDCONST-NEXT: entry: @@ -42,8 +41,7 @@ class ConstantSpec : XCTestCase { let builder = IRBuilder(module: module) // UNSIGNEDCONST: define i64 @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: IntType.int64)) + type: FunctionType([], IntType.int64)) let constant = IntType.int64.constant(UInt64(42)) // UNSIGNEDCONST-NEXT: entry: @@ -70,8 +68,7 @@ class ConstantSpec : XCTestCase { let builder = IRBuilder(module: module) // FLOATINGCONST: define i64 @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: IntType.int64)) + type: FunctionType([], IntType.int64)) let constant = FloatType.double.constant(42.0) // FLOATINGCONST-NEXT: entry: @@ -98,8 +95,7 @@ class ConstantSpec : XCTestCase { let builder = IRBuilder(module: module) // STRUCTCONST: define i64 @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: IntType.int64)) + type: FunctionType([], IntType.int64)) let constant = StructType(elementTypes: [IntType.int64]) .constant(values: [42]) @@ -121,8 +117,7 @@ class ConstantSpec : XCTestCase { let builder = IRBuilder(module: module) // STRUCTCONSTGETELEMENT: define i64 @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: IntType.int64)) + type: FunctionType([], IntType.int64)) let constant = StructType(elementTypes: [IntType.int64]) .constant(values: [42]) @@ -148,8 +143,7 @@ class ConstantSpec : XCTestCase { let vecTy = VectorType(elementType: IntType.int32, count: 4) // VECTORCONSTSHUFFLE-IDENTITY: define <4 x i32> @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: vecTy)) + type: FunctionType([], vecTy)) let vec1 = vecTy.constant([ 1, 2, 3, 4 ] as [Int32]) let mask = vecTy.constant([ 0, 1, 2, 3 ] as [Int32]) @@ -175,8 +169,7 @@ class ConstantSpec : XCTestCase { let maskTy = VectorType(elementType: IntType.int32, count: 8) // VECTORCONSTSHUFFLE: define <8 x i32> @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: maskTy)) + type: FunctionType([], maskTy)) let vecTy = VectorType(elementType: IntType.int32, count: 4) let vec1 = vecTy.constant([ 1, 2, 3, 4 ] as [Int32]) diff --git a/Tests/LLVMTests/DIBuilderSpec.swift b/Tests/LLVMTests/DIBuilderSpec.swift new file mode 100644 index 00000000..f518d0ac --- /dev/null +++ b/Tests/LLVMTests/DIBuilderSpec.swift @@ -0,0 +1,102 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +class DIBuilderSpec : XCTestCase { + func testDIBuilder() { + XCTAssertTrue(fileCheckOutput(of: .stderr, withPrefixes: ["DIBUILDER"]) { + // DIBUILDER: ; ModuleID = 'DIBuilderTest' + let module = Module(name: "DIBuilderTest") + // DIBUILDER: source_filename = "DIBuilderTest" + let builder = IRBuilder(module: module) + let debugBuilder = DIBuilder(module: module) + + let f = builder.addFunction("foo", type: FunctionType([], VoidType())) + let bb = f.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: bb) + _ = builder.buildAlloca(type: IntType.int8) + + // DIBUILDER-DAG: !{{[0-9]+}} = !DIFile(filename: "test.trill", directory: "/") + let file = debugBuilder.buildFile(named: "test.trill", in: "/") + // DIBUILDER-DAG: !{{[0-9]+}} = distinct !DICompileUnit(language: DW_LANG_Swift, file: !{{[0-9]+}}, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !{{[0-9]+}}, splitDebugInlining: false) + _ = debugBuilder.buildCompileUnit(for: .swift, in: file, kind: .full, optimized: false, runtimeVersion: 0) + debugBuilder.finalize() + module.dump() + }) + } + + func testDIExpression() { + XCTAssertTrue(fileCheckOutput(of: .stderr, withPrefixes: ["DIEXPRESSION"]) { + // DIEXPRESSION: ; ModuleID = 'DIExpressionTest' + let module = Module(name: "DIExpressionTest") + // DIEXPRESSION: source_filename = "DIExpressionTest" + let builder = IRBuilder(module: module) + let debugBuilder = DIBuilder(module: module) + + let file = debugBuilder.buildFile(named: "test.trill", in: "/") + let cu = debugBuilder.buildCompileUnit(for: .swift, in: file, kind: .full, optimized: false, runtimeVersion: 0) + + let global = builder.addGlobal("global", type: IntType.int32) + global.initializer = IntType.int32.constant(5) + let globalTy = debugBuilder.buildBasicType(named: "int32_t", encoding: .signed, flags: [], size: Size(bits: 32)) + + // DIEXPRESSION: !{{[0-9]+}} = !DIGlobalVariableExpression(var: !{{[0-9]+}}, expr: !DIExpression()) + // DIEXPRESSION: !{{[0-9]+}} = distinct !DIGlobalVariable(name: "global", linkageName: "global", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 42, type: !{{[0-9]+}}, isLocal: true, isDefinition: true) + // DIEXPRESSION: !{{[0-9]+}} = !DIBasicType(name: "int32_t", size: 32, encoding: DW_ATE_signed) + // DIEXPRESSION: !{{[0-9]+}} = !DIGlobalVariableExpression(var: !{{[0-9]+}}, expr: !{{[0-9]+}}) + let expr = debugBuilder.buildGlobalExpression( + named: "global", linkageName: "global", type: globalTy, + scope: cu, file: file, line: 42, alignment: global.alignment) + // DIEXPRESSION: !{{[0-9]+}} = distinct !DIGlobalVariable(name: "unattached", linkageName: "unattached", scope: !0, file: !{{[0-9]+}}, line: 42, type: !{{[0-9]+}}, isLocal: true, isDefinition: true) + _ = debugBuilder.buildGlobalExpression( + named: "unattached", linkageName: "unattached", + type: globalTy, scope: cu, file: file, line: 42, + isLocal: true, + expression: expr, declaration: nil, alignment: .zero) + + // DIEXPRESSION: !{{[0-9]+}} = !DIGlobalVariableExpression(var: !{{[0-9]+}}, expr: !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 3, DW_OP_constu, 3, DW_OP_plus, DW_OP_deref, DW_OP_constu, 3, DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef, DW_OP_constu, 42, DW_OP_stack_value)) + let addrExpr = debugBuilder.buildExpression([ + .deref, + .plus_uconst(3), + .constu(3), .plus, + .deref, .constu(3), + .constu(2), .swap, .xderef, + .constu(42), .stackValue + ]) + // !10 = distinct !DIGlobalVariable(name: "unattached_addrExpr", linkageName: "unattached_addrExpr", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 42, type: !{{[0-9]+}}, isLocal: true, isDefinition: true) + _ = debugBuilder.buildGlobalExpression( + named: "unattached_addrExpr", linkageName: "unattached_addrExpr", + type: globalTy, scope: cu, file: file, line: 42, + isLocal: true, + expression: addrExpr, declaration: nil, alignment: .zero) + + debugBuilder.finalize() + module.dump() +// try! module.verify() + }) + } + + func testDIScopeAccessors() { + let module = Module(name: "DISCope") + let debugBuilder = DIBuilder(module: module) + + let directory = "/some/long/directory/name" + let fileName = "test.trill" + let file = debugBuilder.buildFile(named: fileName, in: directory) + let cu = debugBuilder.buildCompileUnit(for: .swift, in: file, kind: .full, optimized: false, runtimeVersion: 0) + + XCTAssertEqual(cu.file?.name, fileName) + XCTAssertEqual(cu.file?.directory, directory) + // FIXME: Empty, for now. Need hashing and DWARF 5 source text bindings. + XCTAssertEqual(cu.file?.source, "") + } + + #if !os(macOS) + static var allTests = testCase([ + ("testDIBuilder", testDIBuilder), + ("testDIExpression", testDIExpression), + ("testDIScopeAccessors", testDIScopeAccessors), + ]) + #endif +} diff --git a/Tests/LLVMTests/IRAttributesSpec.swift b/Tests/LLVMTests/IRAttributesSpec.swift new file mode 100644 index 00000000..c01f2c3e --- /dev/null +++ b/Tests/LLVMTests/IRAttributesSpec.swift @@ -0,0 +1,255 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +class IRAttributesSpec : XCTestCase { + func testIRAttributes() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["FNATTR"]) { + // FNATTR: ; ModuleID = '[[ModuleName:IRBuilderTest]]' + // FNATTR-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRBuilderTest") + let builder = IRBuilder(module: module) + let fn = builder.addFunction("fn", + type: FunctionType([IntType.int32, IntType.int32], + IntType.int32)) + + // FNATTR: define i32 @fn(i32 %0, i32 %1) #0 { + fn.addAttribute(.nounwind, to: .function) + + // FNATTR-NEXT: entry: + let entry = fn.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + // FNATTR-NEXT: ret i32 0 + builder.buildRet(IntType.int32.constant(0)) + // FNATTR-NEXT: } + // FNATTR: attributes #0 = { nounwind } + module.dump() + }) + + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["RVATTR"]) { + // RVATTR: ; ModuleID = '[[ModuleName:IRBuilderTest]]' + // RVATTR-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRBuilderTest") + let builder = IRBuilder(module: module) + let fn = builder.addFunction("fn", + type: FunctionType([IntType.int32, IntType.int32], + IntType.int32)) + + // RVATTR: define signext i32 @fn(i32 %0, i32 %1) { + fn.addAttribute(.signext, to: .returnValue) + + // RVATTR-NEXT: entry: + let entry = fn.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + // RVATTR-NEXT: ret i32 0 + builder.buildRet(IntType.int32.constant(0)) + // RVATTR-NEXT: } + module.dump() + }) + + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["ARGATTR"]) { + // ARGATTR: ; ModuleID = '[[ModuleName:IRBuilderTest]]' + // ARGATTR-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRBuilderTest") + let builder = IRBuilder(module: module) + let i8ptr = PointerType(pointee: IntType.int8) + let fn = builder.addFunction("fn", + type: FunctionType([IntType.int32, i8ptr], + IntType.int32)) + + // ARGATTR: define i32 @fn(i32 zeroext %0, i8* align 8 %1) { + fn.addAttribute(.zeroext, to: .argument(0)) + fn.addAttribute(.align, value: 8, to: .argument(1)) + + // ARGATTR-NEXT: entry: + let entry = fn.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + // ARGATTR-NEXT: ret i32 0 + builder.buildRet(IntType.int32.constant(0)) + // ARGATTR-NEXT: } + module.dump() + }) + } + + func testSetUnsetFunctionAttributes() { + let module = Module(name: "FNATTR") + let builder = IRBuilder(module: module) + + let i8ptr = PointerType(pointee: IntType.int8) + let fn = builder.addFunction("fn", + type: FunctionType([i8ptr], i8ptr)) + + // MARK: Enum attributes + + var enumAttr: EnumAttribute + let fnAttrs: [AttributeKind: UInt64] = [ + .alignstack: 8, + .allocsize: 8, + .alwaysinline: 0, + .builtin: 0, + .cold: 0, + .convergent: 0, + .inaccessiblememonly: 0, + .inaccessiblememOrArgmemonly: 0, + .inlinehint: 0, + .jumptable: 0, + .minsize: 0, + .naked: 0, + .noJumpTables: 0, + .nobuiltin: 0, + .noduplicate: 0, + .noimplicitfloat: 0, + .noinline: 0, + .nonlazybind: 0, + .noredzone: 0, + .noreturn: 0, + .norecurse: 0, + .nounwind: 0, + .optnone: 0, + .optsize: 0, + .readnone: 0, + .readonly: 0, + .writeonly: 0, + .argmemonly: 0, + .returnsTwice: 0, + .safestack: 0, + .sanitizeAddress: 0, + .sanitizeMemory: 0, + .sanitizeThread: 0, + .sanitizeHWAddress: 0, + .speculatable: 0, + .ssp: 0, + .sspreq: 0, + .sspstrong: 0, + .strictfp: 0, + .uwtable: 0, + ] + + for (attrKind, value) in fnAttrs { + enumAttr = fn.addAttribute(attrKind, value: value, to: .function) + XCTAssertEqual(enumAttr.value, value) + XCTAssert(fn.attributes(at: .function).contains { $0.asLLVM() == enumAttr.asLLVM() }) + + fn.removeAttribute(enumAttr, from: .function) + XCTAssertFalse(fn.attributes(at: .function).contains { $0.asLLVM() == enumAttr.asLLVM() }) + + enumAttr = fn.addAttribute(attrKind, value: value, to: .function) + fn.removeAttribute(attrKind, from: .function) + XCTAssertFalse(fn.attributes(at: .function).contains { $0.asLLVM() == enumAttr.asLLVM() }) + } + + // MARK: String attributes + + var stringAttr: StringAttribute + for (name, value) in [("foo", ""), ("foo", "bar")] { + stringAttr = fn.addAttribute(name, value: value, to: .function) + XCTAssertEqual(stringAttr.name, name) + XCTAssertEqual(stringAttr.value, value) + XCTAssert(fn.attributes(at: .function).contains { $0.asLLVM() == stringAttr.asLLVM() }) + + fn.removeAttribute(stringAttr, from: .function) + XCTAssertFalse(fn.attributes(at: .function).contains { $0.asLLVM() == stringAttr.asLLVM() }) + + stringAttr = fn.addAttribute(name, to: .function) + fn.removeAttribute(name, from: .function) + XCTAssertFalse(fn.attributes(at: .function).contains { $0.asLLVM() == stringAttr.asLLVM() }) + } + } + + func testSetUnsetArgumentAttributes() { + let module = Module(name: "ARGATTR") + let builder = IRBuilder(module: module) + + let i8ptr = PointerType(pointee: IntType.int8) + let fn = builder.addFunction("fn", + type: FunctionType([i8ptr], i8ptr)) + + // MARK: Enum attributes + + var enumAttr: EnumAttribute + let argAttrs: [AttributeKind: UInt64] = [ + .zeroext: 0, + .signext: 0, + .inreg: 0, + .byval: 0, + .inalloca: 0, + .sret: 0, + .align: 8, + .noalias: 0, + .nocapture: 0, + .nest: 0, + .returned: 0, + .nonnull: 0, + .dereferenceable: 8, + .dereferenceableOrNull: 8, + .swiftself: 0, + .swifterror: 0, + ] + + for (attrKind, value) in argAttrs { + enumAttr = fn.addAttribute(attrKind, value: value, to: .returnValue) + XCTAssertEqual(enumAttr.value, value) + XCTAssert(fn.attributes(at: .returnValue).contains { $0.asLLVM() == enumAttr.asLLVM() }) + + fn.removeAttribute(enumAttr, from: .returnValue) + XCTAssertFalse(fn.attributes(at: .returnValue).contains { $0.asLLVM() == enumAttr.asLLVM() }) + + enumAttr = fn.addAttribute(attrKind, value: value, to: .returnValue) + fn.removeAttribute(attrKind, from: .returnValue) + XCTAssertFalse(fn.attributes(at: .returnValue).contains { $0.asLLVM() == enumAttr.asLLVM() }) + } + + for (attrKind, value) in argAttrs { + enumAttr = fn.addAttribute(attrKind, value: value, to: .argument(0)) + XCTAssertEqual(enumAttr.value, value) + XCTAssert(fn.attributes(at: .argument(0)).contains { $0.asLLVM() == enumAttr.asLLVM() }) + + fn.removeAttribute(enumAttr, from: .argument(0)) + XCTAssertFalse(fn.attributes(at: .argument(0)).contains { $0.asLLVM() == enumAttr.asLLVM() }) + + enumAttr = fn.addAttribute(attrKind, value: value, to: .argument(0)) + fn.removeAttribute(attrKind, from: .argument(0)) + XCTAssertFalse(fn.attributes(at: .argument(0)).contains { $0.asLLVM() == enumAttr.asLLVM() }) + } + + // MARK: String attributes + + var stringAttr: StringAttribute + for (name, value) in [("foo", ""), ("foo", "bar")] { + stringAttr = fn.addAttribute(name, value: value, to: .returnValue) + XCTAssertEqual(stringAttr.name, name) + XCTAssertEqual(stringAttr.value, value) + XCTAssert(fn.attributes(at: .returnValue).contains { $0.asLLVM() == stringAttr.asLLVM() }) + + fn.removeAttribute(stringAttr, from: .returnValue) + XCTAssertFalse(fn.attributes(at: .returnValue).contains { $0.asLLVM() == stringAttr.asLLVM() }) + + stringAttr = fn.addAttribute(name, to: .returnValue) + fn.removeAttribute(name, from: .returnValue) + XCTAssertFalse(fn.attributes(at: .returnValue).contains { $0.asLLVM() == stringAttr.asLLVM() }) + } + + for (name, value) in [("foo", ""), ("foo", "bar")] { + stringAttr = fn.addAttribute(name, value: value, to: .argument(0)) + XCTAssertEqual(stringAttr.name, name) + XCTAssertEqual(stringAttr.value, value) + XCTAssert(fn.attributes(at: .argument(0)).contains { $0.asLLVM() == stringAttr.asLLVM() }) + + fn.removeAttribute(stringAttr, from: .argument(0)) + XCTAssertFalse(fn.attributes(at: .argument(0)).contains { $0.asLLVM() == stringAttr.asLLVM() }) + + stringAttr = fn.addAttribute(name, to: .argument(0)) + fn.removeAttribute(name, from: .argument(0)) + XCTAssertFalse(fn.attributes(at: .argument(0)).contains { $0.asLLVM() == stringAttr.asLLVM() }) + } + } + + #if !os(macOS) + static var allTests = testCase([ + ("testIRAttributes", testIRAttributes), + ("testSetUnsetFunctionAttributes", testSetUnsetFunctionAttributes), + ("testSetUnsetArgumentAttributes", testSetUnsetArgumentAttributes), + ]) + #endif +} diff --git a/Tests/LLVMTests/IRBuilderSpec.swift b/Tests/LLVMTests/IRBuilderSpec.swift index 9496e6a7..b134023f 100644 --- a/Tests/LLVMTests/IRBuilderSpec.swift +++ b/Tests/LLVMTests/IRBuilderSpec.swift @@ -12,8 +12,8 @@ class IRBuilderSpec : XCTestCase { let builder = IRBuilder(module: module) // IRBUILDER: define void @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: VoidType())) + type: FunctionType([], + VoidType())) // IRBUILDER-NEXT: entry: let entry = main.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entry) @@ -23,6 +23,41 @@ class IRBuilderSpec : XCTestCase { module.dump() }) + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRBUILDER-INLINE-ASM"]) { + // IRBUILDER-INLINE-ASM: ; ModuleID = '[[ModuleName:IRBuilderInlineAsmTest]]' + // IRBUILDER-INLINE-ASM-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRBuilderInlineAsmTest") + let builder = IRBuilder(module: module) + + // IRBUILDER-INLINE-ASM: module asm "i32 (i32) asm \22bswap $0\22, \22=r,r\22" + module.appendInlineAssembly(""" + i32 (i32) asm "bswap $0", "=r,r" + """) + // IRBUILDER-INLINE-ASM-NEXT: %X = call i32 asm \22bswap $0\22, \22=r,r\22(i32 %Y) + module.appendInlineAssembly(""" + %X = call i32 asm "bswap $0", "=r,r"(i32 %Y) + """) + + // IRBUILDER-INLINE-ASM: @a = global i32 1 + let g1 = builder.addGlobal("a", type: IntType.int32) + g1.initializer = Int32(1) + + // IRBUILDER-INLINE-ASM: define void @main() { + let main = builder.addFunction("main", + type: FunctionType([], VoidType())) + // IRBUILDER-INLINE-ASM-NEXT: entry: + let entry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + let ty = FunctionType([ PointerType(pointee: IntType.int32) ], VoidType()) + let emptyASM = builder.buildInlineAssembly("", dialect: .att, type: ty, constraints: "=r,0", hasSideEffects: true, needsAlignedStack: true) + // IRBUILDER-INLINE-ASM-NEXT: call void asm sideeffect alignstack "\00", "=r,0\00"(i32* @a) + _ = builder.buildCall(emptyASM, args: [ g1 ]) + // IRBUILDER-INLINE-ASM-NEXT: ret void + builder.buildRetVoid() + // IRBUILDER-INLINE-ASM-NEXT: } + module.dump() + }) + // MARK: Arithmetic Instructions XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRBUILDERARITH"]) { @@ -33,35 +68,34 @@ class IRBuilderSpec : XCTestCase { // IRBUILDERARITH: @a = global i32 1 // IRBUILDERARITH-NEXT: @b = global i32 1 - var g1 = builder.addGlobal("a", type: IntType.int32) + let g1 = builder.addGlobal("a", type: IntType.int32) g1.initializer = Int32(1) - var g2 = builder.addGlobal("b", type: IntType.int32) + let g2 = builder.addGlobal("b", type: IntType.int32) g2.initializer = Int32(1) - // IRBUILDERARITH-NEXT: @vec1 = global <8 x i64> - // IRBUILDERARITH-NEXT: @vec2 = global <8 x i64> + // IRBUILDERARITH-NEXT: @vec1 = global <8 x i32> + // IRBUILDERARITH-NEXT: @vec2 = global <8 x i32> let vecTy = VectorType(elementType: IntType.int32, count: 8) - let gVec1 = builder.addGlobal("vec1", initializer: vecTy.constant([ 1, 1, 1, 1, 1, 1, 1, 1 ])) - let gVec2 = builder.addGlobal("vec2", initializer: vecTy.constant([ 2, 2, 2, 2, 2, 2, 2, 2 ])) + let gVec1 = builder.addGlobal("vec1", initializer: vecTy.constant([ 1, 1, 1, 1, 1, 1, 1, 1 ] as [Int32])) + let gVec2 = builder.addGlobal("vec2", initializer: vecTy.constant([ 2, 2, 2, 2, 2, 2, 2, 2 ] as [Int32])) // IRBUILDERARITH: define void @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: VoidType())) + type: FunctionType([], VoidType())) // IRBUILDERARITH-NEXT: entry: let entry = main.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entry) // IRBUILDERARITH-NEXT: [[A_LOAD:%[0-9]+]] = load i32, i32* @a - let vg1 = builder.buildLoad(g1) + let vg1 = builder.buildLoad(g1, type: IntType.int32) // IRBUILDERARITH-NEXT: [[B_LOAD:%[0-9]+]] = load i32, i32* @b - let vg2 = builder.buildLoad(g2) + let vg2 = builder.buildLoad(g2, type: IntType.int32) - // IRBUILDERARITH-NEXT: [[VEC1_LOAD:%[0-9]+]] = load <8 x i64>, <8 x i64>* @vec1 - let vgVec1 = builder.buildLoad(gVec1) + // IRBUILDERARITH-NEXT: [[VEC1_LOAD:%[0-9]+]] = load <8 x i32>, <8 x i32>* @vec1 + let vgVec1 = builder.buildLoad(gVec1, type: vecTy) - // IRBUILDERARITH-NEXT: [[VEC2_LOAD:%[0-9]+]] = load <8 x i64>, <8 x i64>* @vec2 - let vgVec2 = builder.buildLoad(gVec2) + // IRBUILDERARITH-NEXT: [[VEC2_LOAD:%[0-9]+]] = load <8 x i32>, <8 x i32>* @vec2 + let vgVec2 = builder.buildLoad(gVec2, type: vecTy) // IRBUILDERARITH-NEXT: {{%[0-9]+}} = add i32 [[A_LOAD]], [[B_LOAD]] _ = builder.buildAdd(vg1, vg2) @@ -88,15 +122,15 @@ class IRBuilderSpec : XCTestCase { // IRBUILDERARITH-NEXT: {{%[0-9]+}} = mul nuw i32 [[A_LOAD]], [[B_LOAD]] _ = builder.buildMul(vg1, vg2, overflowBehavior: .noUnsignedWrap) - // IRBUILDERARITH-NEXT: {{%[0-9]+}} = add <8 x i64> [[VEC1_LOAD]], [[VEC2_LOAD]] + // IRBUILDERARITH-NEXT: {{%[0-9]+}} = add <8 x i32> [[VEC1_LOAD]], [[VEC2_LOAD]] _ = builder.buildAdd(vgVec1, vgVec2) - // IRBUILDERARITH-NEXT: {{%[0-9]+}} = sub <8 x i64> [[VEC1_LOAD]], [[VEC2_LOAD]] + // IRBUILDERARITH-NEXT: {{%[0-9]+}} = sub <8 x i32> [[VEC1_LOAD]], [[VEC2_LOAD]] _ = builder.buildSub(vgVec1, vgVec2) - // IRBUILDERARITH-NEXT: {{%[0-9]+}} = mul <8 x i64> [[VEC1_LOAD]], [[VEC2_LOAD]] + // IRBUILDERARITH-NEXT: {{%[0-9]+}} = mul <8 x i32> [[VEC1_LOAD]], [[VEC2_LOAD]] _ = builder.buildMul(vgVec1, vgVec2) - // IRBUILDERARITH-NEXT: {{%[0-9]+}} = sdiv <8 x i64> [[VEC1_LOAD]], [[VEC2_LOAD]] + // IRBUILDERARITH-NEXT: {{%[0-9]+}} = sdiv <8 x i32> [[VEC1_LOAD]], [[VEC2_LOAD]] _ = builder.buildDiv(vgVec1, vgVec2, signed: true) - // IRBUILDERARITH-NEXT: {{%[0-9]+}} = udiv <8 x i64> [[VEC1_LOAD]], [[VEC2_LOAD]] + // IRBUILDERARITH-NEXT: {{%[0-9]+}} = udiv <8 x i32> [[VEC1_LOAD]], [[VEC2_LOAD]] _ = builder.buildDiv(vgVec1, vgVec2, signed: false) // IRBUILDERARITH-NEXT: {{%[0-9]+}} = sub i32 0, [[A_LOAD]] @@ -121,23 +155,22 @@ class IRBuilderSpec : XCTestCase { // IRBUILDERCMP: @a = global i32 1 // IRBUILDERCMP-NEXT: @b = global i32 1 - var g1 = builder.addGlobal("a", type: IntType.int32) + let g1 = builder.addGlobal("a", type: IntType.int32) g1.initializer = Int32(1) - var g2 = builder.addGlobal("b", type: IntType.int32) + let g2 = builder.addGlobal("b", type: IntType.int32) g2.initializer = Int32(1) // IRBUILDERCMP: define void @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: VoidType())) + type: FunctionType([], VoidType())) // IRBUILDERCMP-NEXT: entry: let entry = main.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entry) // IRBUILDERCMP-NEXT: %0 = load i32, i32* @a - let vg1 = builder.buildLoad(g1) + let vg1 = builder.buildLoad(g1, type: IntType.int32) // IRBUILDERCMP-NEXT: %1 = load i32, i32* @b - let vg2 = builder.buildLoad(g2) + let vg2 = builder.buildLoad(g2, type: IntType.int32) // IRBUILDERCMP-NEXT: %2 = icmp eq i32 %0, %1 _ = builder.buildICmp(vg1, vg2, .equal) @@ -175,23 +208,22 @@ class IRBuilderSpec : XCTestCase { // IRBUILDERFCMP: @a = global double 1 // IRBUILDERFCMP-NEXT: @b = global double 1 - var g1 = builder.addGlobal("a", type: FloatType.double) + let g1 = builder.addGlobal("a", type: FloatType.double) g1.initializer = FloatType.double.constant(1) - var g2 = builder.addGlobal("b", type: FloatType.double) + let g2 = builder.addGlobal("b", type: FloatType.double) g2.initializer = FloatType.double.constant(1) // IRBUILDERFCMP: define void @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: VoidType())) + type: FunctionType([], VoidType())) // IRBUILDERFCMP-NEXT: entry: let entry = main.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entry) // IRBUILDERFCMP-NEXT: %0 = load double, double* @a - let vg1 = builder.buildLoad(g1) + let vg1 = builder.buildLoad(g1, type: FloatType.double) // IRBUILDERFCMP-NEXT: %1 = load double, double* @b - let vg2 = builder.buildLoad(g2) + let vg2 = builder.buildLoad(g2, type: FloatType.double) // IRBUILDERFCMP-NEXT: %2 = fcmp oeq double %0, %1 _ = builder.buildFCmp(vg1, vg2, .orderedEqual) @@ -233,8 +265,7 @@ class IRBuilderSpec : XCTestCase { // CONTROLFLOW: define i32 @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: IntType.int32)) + type: FunctionType([], IntType.int32)) // CONTROLFLOW-NEXT: entry: let entry = main.appendBasicBlock(named: "entry") @@ -253,7 +284,7 @@ class IRBuilderSpec : XCTestCase { builder.buildStore(IntType.int64.constant(1), to: variable, ordering: .sequentiallyConsistent) // CONTROLFLOW-NEXT: %0 = load i64, i64* %var - let load = builder.buildLoad(variable) + let load = builder.buildLoad(variable, type: IntType.int64) // CONTROLFLOW-NEXT: %1 = icmp eq i64 %0, 0 let res = builder.buildICmp(load, IntType.int64.zero(), .equal) @@ -283,54 +314,54 @@ class IRBuilderSpec : XCTestCase { // MARK: Cast Instructions XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["CAST"]) { - // CAST: ; ModuleID = '[[ModuleName:IRBuilderTest]]' - // CAST-NEXT: source_filename = "[[ModuleName]]" - let module = Module(name: "IRBuilderTest") - let builder = IRBuilder(module: module) + // CAST: ; ModuleID = '[[ModuleName:IRBuilderTest]]' + // CAST-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRBuilderTest") + let builder = IRBuilder(module: module) - // CAST: define i32 @main() { - let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: IntType.int32)) + // CAST: define i32 @main() { + let main = builder.addFunction("main", + type: FunctionType([], + IntType.int32)) - // CAST-NEXT: entry: - let entry = main.appendBasicBlock(named: "entry") - builder.positionAtEnd(of: entry) + // CAST-NEXT: entry: + let entry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) - // CAST-NEXT: %0 = alloca i64 - let alloca = builder.buildAlloca(type: IntType.int64) + // CAST-NEXT: %0 = alloca i64 + let alloca = builder.buildAlloca(type: IntType.int64) - // CAST-NEXT: %1 = ptrtoint i64* %0 to i64 - _ = builder.buildPtrToInt(alloca, type: IntType.int64) + // CAST-NEXT: %1 = ptrtoint i64* %0 to i64 + _ = builder.buildPtrToInt(alloca, type: IntType.int64) - // CAST-NEXT: %2 = load i64, i64* %0 - let val = builder.buildLoad(alloca) + // CAST-NEXT: %2 = load i64, i64* %0 + let val = builder.buildLoad(alloca, type: IntType.int64) - // CAST-NEXT: %3 = inttoptr i64 %2 to i64* - _ = builder.buildIntToPtr(val, - type: PointerType(pointee: IntType.int64)) + // CAST-NEXT: %3 = inttoptr i64 %2 to i64* + _ = builder.buildIntToPtr(val, + type: PointerType(pointee: IntType.int64)) - // CAST-NEXT: %4 = bitcast i64* %0 to i8* - _ = builder.buildBitCast(alloca, type: PointerType.toVoid) + // CAST-NEXT: %4 = bitcast i64* %0 to i8* + _ = builder.buildBitCast(alloca, type: PointerType.toVoid) - // CAST-NEXT: %5 = alloca double - let dblAlloca = builder.buildAlloca(type: FloatType.double) + // CAST-NEXT: %5 = alloca double + let dblAlloca = builder.buildAlloca(type: FloatType.double) - // CAST-NEXT: %6 = load double, double* %5 - let dblVal = builder.buildLoad(dblAlloca) + // CAST-NEXT: %6 = load double, double* %5 + let dblVal = builder.buildLoad(dblAlloca, type: FloatType.double) - // CAST-NEXT: %7 = fptrunc double %6 to float - let fltVal = builder.buildFPCast(dblVal, type: FloatType.float) + // CAST-NEXT: %7 = fptrunc double %6 to float + let fltVal = builder.buildFPCast(dblVal, type: FloatType.float) - // CAST-NEXT: %8 = fpext float %7 to double - _ = builder.buildFPCast(fltVal, type: FloatType.double) + // CAST-NEXT: %8 = fpext float %7 to double + _ = builder.buildFPCast(fltVal, type: FloatType.double) - // CAST-NEXT: ret i32 0 - builder.buildRet(IntType.int32.constant(0)) + // CAST-NEXT: ret i32 0 + builder.buildRet(IntType.int32.constant(0)) - // CAST-NEXT: } - module.dump() + // CAST-NEXT: } + module.dump() }) // MARK: C Standard Library Instructions diff --git a/Tests/LLVMTests/IRExceptionSpec.swift b/Tests/LLVMTests/IRExceptionSpec.swift index 81b84a7f..1fadf593 100644 --- a/Tests/LLVMTests/IRExceptionSpec.swift +++ b/Tests/LLVMTests/IRExceptionSpec.swift @@ -17,8 +17,7 @@ class IRExceptionSpec : XCTestCase { let builder = IRBuilder(module: module) // IRRESUME: define void @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: VoidType())) + type: FunctionType([], VoidType())) // IRRESUME-NEXT: entry: let entry = main.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entry) @@ -39,8 +38,7 @@ class IRExceptionSpec : XCTestCase { let builder = IRBuilder(module: module) // IRCLEANUP: define void @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: VoidType())) + type: FunctionType([], VoidType())) // IRCLEANUP-NEXT: entry: let entry = main.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entry) @@ -66,8 +64,7 @@ class IRExceptionSpec : XCTestCase { // IRCATCH: define void @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: VoidType())) + type: FunctionType([], VoidType())) // IRCATCH-NEXT: entry: let entry = main.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entry) @@ -95,8 +92,7 @@ class IRExceptionSpec : XCTestCase { // IRCATCHFILTER: define void @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: VoidType())) + type: FunctionType([], VoidType())) // IRCATCHFILTER-NEXT: entry: let entry = main.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entry) diff --git a/Tests/LLVMTests/IRGlobalSpec.swift b/Tests/LLVMTests/IRGlobalSpec.swift new file mode 100644 index 00000000..cd8ac974 --- /dev/null +++ b/Tests/LLVMTests/IRGlobalSpec.swift @@ -0,0 +1,91 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +class IRGlobalSpec : XCTestCase { + func testIRInertGlobal() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRINERTGLOBAL"]) { + // IRINERTGLOBAL: ; ModuleID = '[[ModuleName:IRInertGlobalTest]]' + // IRINERTGLOBAL-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRInertGlobalTest") + let builder = IRBuilder(module: module) + // IRINERTGLOBAL: @external_global = external constant i32 + let extGlobal = builder.addGlobal("external_global", type: IntType.int32) + extGlobal.isGlobalConstant = true + // IRINERTGLOBAL: @got.external_global = private unnamed_addr constant i32* @external_global + var gotGlobal = builder.addGlobal("got.external_global", + initializer: extGlobal) + gotGlobal.linkage = .`private` + gotGlobal.unnamedAddressKind = .global + gotGlobal.isGlobalConstant = true + + // IRINERTGLOBAL: @external_relative_reference = global i32 trunc (i64 sub (i64 ptrtoint (i32** @got.external_global to i64), i64 ptrtoint (i32* @external_relative_reference to i64)) to i32) + let ext_relative_reference = builder.addGlobal("external_relative_reference", type: IntType.int32) + ext_relative_reference.initializer = Constant.pointerToInt(gotGlobal, .int64) + .subtracting(Constant.pointerToInt(ext_relative_reference, .int64)).truncate(to: .int32) + module.dump() + }) + } + + func testIRCOMDATGlobal() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRCOMDATGLOBAL"]) { + // IRCOMDATGLOBAL: ; ModuleID = '[[ModuleName:IRCOMDATGLOBALTest]]' + // IRCOMDATGLOBAL-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRCOMDATGLOBALTest") + let builder = IRBuilder(module: module) + + // IRCOMDATGLOBAL: $test_any = comdat any + let comdatAnySec = module.comdat(named: "test_any") + comdatAnySec.selectionKind = .any + + // IRCOMDATGLOBAL: $test_largest = comdat largest + let comdatLargestSec = module.comdat(named: "test_largest") + comdatLargestSec.selectionKind = .largest + + // IRCOMDATGLOBAL: $test_no_dupes = comdat noduplicates + let comdatNoDupesSec = module.comdat(named: "test_no_dupes") + comdatNoDupesSec.selectionKind = .noDuplicates + + // IRCOMDATGLOBAL: $test_same_size = comdat samesize + let comdatSameSizeSec = module.comdat(named: "test_same_size") + comdatSameSizeSec.selectionKind = .sameSize + + // IRCOMDATGLOBAL: $test_exact_match = comdat exactmatch + let comdatExactSec = module.comdat(named: "test_exact_match") + comdatExactSec.selectionKind = .exactMatch + + let i = IntType.int8.constant(42) + + // IRCOMDATGLOBAL: @comdat_global_any = global i8 42, comdat($test_any) + var comdatGlobalAny = builder.addGlobal("comdat_global_any", initializer: i) + comdatGlobalAny.comdat = comdatAnySec + + // IRCOMDATGLOBAL: @comdat_global_largest = global i8 42, comdat($test_largest) + var comdatGlobalLargest = builder.addGlobal("comdat_global_largest", initializer: i) + comdatGlobalLargest.comdat = comdatLargestSec + + // IRCOMDATGLOBAL: @comdat_global_no_dupes = global i8 42, comdat($test_no_dupes) + var comdatGlobalNoDupes = builder.addGlobal("comdat_global_no_dupes", initializer: i) + comdatGlobalNoDupes.comdat = comdatNoDupesSec + + // IRCOMDATGLOBAL: @comdat_global_same_size = global i8 42, comdat($test_same_size) + var comdatGlobalSameSize = builder.addGlobal("comdat_global_same_size", initializer: i) + comdatGlobalSameSize.comdat = comdatSameSizeSec + + // IRCOMDATGLOBAL: @comdat_global_exact_match = global i8 42, comdat($test_exact_match) + var comdatGlobalExactMatch = builder.addGlobal("comdat_global_exact_match", initializer: i) + comdatGlobalExactMatch.comdat = comdatExactSec + + module.dump() + }) + } + + #if !os(macOS) + static var allTests = testCase([ + ("testIRInertGlobal", testIRInertGlobal), + ("testIRCOMDATGlobal", testIRCOMDATGlobal), + ]) + #endif +} + diff --git a/Tests/LLVMTests/IRInstructionSpec.swift b/Tests/LLVMTests/IRInstructionSpec.swift new file mode 100644 index 00000000..5dd3448f --- /dev/null +++ b/Tests/LLVMTests/IRInstructionSpec.swift @@ -0,0 +1,123 @@ +import LLVM +import XCTest +import FileCheck +import Foundation +import cllvm + +class IRInstructionSpec : XCTestCase { + func testInstructionOpCodes() { + // N.B. This module does not have to be well-formed. + let module = Module(name: "IRInstructionTest") + let builder = IRBuilder(module: module) + + let structTy = StructType(elementTypes: [ + IntType.int32 + ]) + let global = module.addGlobal("type_info", type: structTy) + + let f = module.addFunction("test", + type: FunctionType([ + IntType.int1, + FloatType.float, + PointerType.toVoid, + structTy, + VectorType(elementType: IntType.int32, count: 42), + ], VoidType())) + let entry = f.appendBasicBlock(named: "entry") + let landing = f.appendBasicBlock(named: "landing") + builder.positionAtEnd(of: landing) + let land = builder.buildLandingPad(returning: VoidType(), clauses: [ + LandingPadClause.catch(global) + ]) + builder.buildRet(land) + + builder.positionAtEnd(of: entry) + + // Use parameter values to guaranteed constant folding is off. + let ival = f.parameters[0] + let fval = f.parameters[1] + let pval = f.parameters[2] + let sval = f.parameters[3] + let vval = f.parameters[4] + for op in OpCode.Binary.allCases { + let opVal = builder.buildBinaryOperation(op, ival, ival) as! IRInstruction + XCTAssertTrue(opVal.isAInstruction) + XCTAssertEqual(opVal.opCode, opVal.opCode) + } + + for op in OpCode.Cast.allCases { + let opVal = builder.buildCast(op, value: fval, type: PointerType.toVoid) as! IRInstruction + XCTAssertTrue(opVal.isAInstruction) + XCTAssertEqual(opVal.opCode, opVal.opCode) + } + + XCTAssertEqual((builder.buildPointerCast(of: pval, to: PointerType(pointee: IntType.int1)) as! IRInstruction).opCode, OpCode.bitCast) + XCTAssertEqual((builder.buildIntCast(of: ival, to: IntType.int32, signed: false) as! IRInstruction).opCode, OpCode.zext) + XCTAssertEqual((builder.buildIntCast(of: ival, to: IntType.int32, signed: true) as! IRInstruction).opCode, OpCode.sext) + XCTAssertEqual((builder.buildNeg(ival) as! IRInstruction).opCode, OpCode.sub) + XCTAssertEqual((builder.buildAdd(ival, ival) as! IRInstruction).opCode, OpCode.add) + XCTAssertEqual((builder.buildSub(ival, ival) as! IRInstruction).opCode, OpCode.sub) + XCTAssertEqual((builder.buildAdd(fval, fval) as! IRInstruction).opCode, OpCode.fadd) + XCTAssertEqual((builder.buildSub(fval, fval) as! IRInstruction).opCode, OpCode.fsub) + XCTAssertEqual((builder.buildMul(ival, ival) as! IRInstruction).opCode, OpCode.mul) + XCTAssertEqual((builder.buildRem(ival, ival, signed: false) as! IRInstruction).opCode, OpCode.urem) + XCTAssertEqual((builder.buildRem(ival, ival, signed: true) as! IRInstruction).opCode, OpCode.srem) + XCTAssertEqual((builder.buildDiv(ival, ival, signed: false) as! IRInstruction).opCode, OpCode.udiv) + XCTAssertEqual((builder.buildDiv(ival, ival, signed: true) as! IRInstruction).opCode, OpCode.sdiv) + XCTAssertEqual((builder.buildICmp(ival, ival, .equal) as! IRInstruction).opCode, OpCode.icmp) + XCTAssertEqual((builder.buildFCmp(fval, fval, .orderedEqual) as! IRInstruction).opCode, OpCode.fcmp) + XCTAssertEqual((builder.buildNot(ival) as! IRInstruction).opCode, OpCode.xor) + XCTAssertEqual((builder.buildXor(ival, ival) as! IRInstruction).opCode, OpCode.xor) + XCTAssertEqual((builder.buildOr(ival, ival) as! IRInstruction).opCode, OpCode.or) + XCTAssertEqual((builder.buildAnd(ival, ival) as! IRInstruction).opCode, OpCode.and) + XCTAssertEqual((builder.buildShl(ival, ival) as! IRInstruction).opCode, OpCode.shl) + XCTAssertEqual((builder.buildShr(ival, ival, isArithmetic: false) as! IRInstruction).opCode, OpCode.lshr) + XCTAssertEqual((builder.buildShr(ival, ival, isArithmetic: true) as! IRInstruction).opCode, OpCode.ashr) + XCTAssertEqual(builder.buildPhi(IntType.int1).opCode, OpCode.phi) + XCTAssertEqual(builder.buildSelect(ival, then: ival, else: ival).opCode, OpCode.select) + XCTAssertEqual(builder.buildSwitch(ival, else: entry, caseCount: 0).opCode, OpCode.switch) + XCTAssertEqual(builder.buildCondBr(condition: ival, then: entry, else: entry).opCode, OpCode.br) + XCTAssertEqual(builder.buildBr(entry).opCode, OpCode.br) + XCTAssertEqual(builder.buildIndirectBr(address: f.address(of: entry)!, destinations: []).opCode, OpCode.indirectBr) + XCTAssertEqual(builder.buildUnreachable().opCode, OpCode.unreachable) + XCTAssertEqual(builder.buildCall(f, args: [ival, fval, pval]).opCode, OpCode.call) + XCTAssertEqual(builder.buildInvoke(f, args: [], next: entry, catch: landing).opCode, OpCode.invoke) + XCTAssertEqual(builder.buildLandingPad(returning: VoidType(), clauses: [ + LandingPadClause.catch(global) + ]).opCode, OpCode.landingPad) + XCTAssertEqual((builder.buildResume(ival) as! IRInstruction).opCode, OpCode.resume) + XCTAssertEqual((builder.buildVAArg(pval, type: PointerType.toVoid) as! IRInstruction).opCode, OpCode.vaArg) + XCTAssertEqual(builder.buildAlloca(type: IntType.int1).opCode, OpCode.alloca) + XCTAssertEqual(builder.buildStore(ival, to: pval).opCode, OpCode.store) + XCTAssertEqual(builder.buildLoad(pval, type: IntType.int8).opCode, OpCode.load) + XCTAssertEqual((builder.buildInBoundsGEP(pval, type: IntType.int8, indices: []) as! IRInstruction).opCode, OpCode.getElementPtr) + XCTAssertEqual((builder.buildGEP(pval, type: IntType.int8, indices: []) as! IRInstruction).opCode, OpCode.getElementPtr) + XCTAssertEqual((builder.buildExtractValue(sval, index: 0) as! IRInstruction).opCode, OpCode.extractValue) + XCTAssertEqual((builder.buildTrunc(ival, type: IntType.int32) as! IRInstruction).opCode, OpCode.trunc) + XCTAssertEqual((builder.buildSExt(ival, type: IntType.int32) as! IRInstruction).opCode, OpCode.sext) + XCTAssertEqual((builder.buildZExt(ival, type: IntType.int32) as! IRInstruction).opCode, OpCode.zext) + XCTAssertEqual((builder.buildIntToPtr(ival, type: PointerType.toVoid) as! IRInstruction).opCode, OpCode.intToPtr) + XCTAssertEqual((builder.buildPtrToInt(pval, type: IntType.int32) as! IRInstruction).opCode, OpCode.ptrToInt) + XCTAssertEqual(builder.buildFence(ordering: .acquire).opCode, OpCode.fence) + XCTAssertEqual((builder.buildAtomicCmpXchg(ptr: pval, of: ival, to: ival, successOrdering: .acquire, failureOrdering: .acquire) as! IRInstruction).opCode, OpCode.atomicCmpXchg) + XCTAssertEqual((builder.buildAtomicRMW(atomicOp: .add, ptr: pval, value: ival, ordering: .acquire) as! IRInstruction).opCode, OpCode.atomicRMW) + XCTAssertEqual(builder.buildMalloc(IntType.int64).opCode, OpCode.bitCast) // malloc-bitcast pair + XCTAssertEqual(builder.buildFree(pval).opCode, OpCode.call) + XCTAssertEqual(builder.buildMemset(to: pval, of: ival, length: 1, alignment: .one).opCode, OpCode.call) + XCTAssertEqual(builder.buildMemCpy(to: pval, .one, from: pval, .one, length: 1).opCode, OpCode.call) + XCTAssertEqual(builder.buildMemMove(to: pval, .one, from: pval, .one, length: 1).opCode, OpCode.call) + XCTAssertEqual((builder.buildInsertValue(aggregate: sval, element: ival, index: 0) as! IRInstruction).opCode, OpCode.insertValue) + XCTAssertEqual((builder.buildExtractValue(sval, index: 0) as! IRInstruction).opCode, OpCode.extractValue) + XCTAssertEqual((builder.buildInsertElement(vector: vval, element: 0, index: 0) as! IRInstruction).opCode, OpCode.insertElement) + XCTAssertEqual((builder.buildExtractElement(vector: vval, index: 0) as! IRInstruction).opCode, OpCode.extractElement) + let mask = VectorType(elementType: IntType.int32, count: 1).undef() + XCTAssertEqual((builder.buildShuffleVector(vval, and: ival, mask: mask) as! IRInstruction).opCode, OpCode.shuffleVector) + XCTAssertEqual(builder.buildRetVoid().opCode, OpCode.ret) + } + + #if !os(macOS) + static var allTests = testCase([ + ("testInstructionOpCodes", testInstructionOpCodes), + ]) + #endif +} diff --git a/Tests/LLVMTests/IRIntrinsicSpec.swift b/Tests/LLVMTests/IRIntrinsicSpec.swift new file mode 100644 index 00000000..21edc900 --- /dev/null +++ b/Tests/LLVMTests/IRIntrinsicSpec.swift @@ -0,0 +1,172 @@ +import LLVM +import XCTest +import FileCheck +import Foundation +import cllvm +import llvmshims + +class IRIntrinsicSpec : XCTestCase { + func testIRIntrinsics() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRINTRINSIC"]) { + // IRINTRINSIC: ; ModuleID = '[[ModuleName:IRIntrinsicTest]]' + // IRINTRINSIC-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRIntrinsicTest") + let builder = IRBuilder(module: module) + + // IRINTRINSIC: define i32 @readOneArg(i32 %0, ...) { + let main = builder.addFunction("readOneArg", + type: FunctionType([IntType.int32], + IntType.int32, + variadic: true)) + // IRINTRINSIC-NEXT: entry: + let entry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + + // IRINTRINSIC-NEXT: [[VA_BUF:%[0-9]+]] = alloca i8* + let ap = builder.buildAlloca(type: PointerType(pointee: IntType.int8)) + // IRINTRINSIC-NEXT: [[CAST_VA_BUF:%[0-9]+]] = bitcast i8** [[VA_BUF]] to i8* + let ap2 = builder.buildBitCast(ap, type: PointerType(pointee: IntType.int8)) + + // IRINTRINSIC-NEXT: call void @llvm.va_start(i8* [[CAST_VA_BUF]]) + let vaStart = module.intrinsic(Intrinsic.ID.llvm_va_start)! + _ = builder.buildCall(vaStart, args: [ ap2 ]) + + // IRINTRINSIC-NEXT: [[RET_VAL:%[0-9]+]] = va_arg i8** [[VA_BUF]], i32 + let tmp = builder.buildVAArg(ap, type: IntType.int32) + + // IRINTRINSIC-NEXT: [[VA_COPY_BUF:%[0-9]+]] = alloca i8* + let aq = builder.buildAlloca(type: PointerType(pointee: IntType.int8)) + // IRINTRINSIC-NEXT: [[CAST_VA_COPY_BUF:%[0-9]+]] = bitcast i8** [[VA_COPY_BUF]] to i8* + let aq2 = builder.buildBitCast(aq, type: PointerType(pointee: IntType.int8)) + + // IRINTRINSIC-NEXT: call void @llvm.va_copy(i8* [[CAST_VA_BUF]], i8* [[CAST_VA_COPY_BUF]]) + let vaCopy = module.intrinsic(Intrinsic.ID.llvm_va_copy)! + _ = builder.buildCall(vaCopy, args: [ ap2, aq2 ]) + + // IRINTRINSIC-NEXT: call void @llvm.va_end(i8* [[CAST_VA_COPY_BUF]]) + let vaEnd = module.intrinsic(Intrinsic.ID.llvm_va_end)! + _ = builder.buildCall(vaEnd, args: [ aq2 ]) + + // IRINTRINSIC-NEXT: i32 [[RET_VAL]] + builder.buildRet(tmp) + // IRINTRINSIC-NEXT: } + module.dump() + + // IRINTRINSIC: ; Function Attrs: nounwind + // IRINTRINSIC-NEXT: declare void @llvm.va_start(i8* %0) #0 + + // IRINTRINSIC: ; Function Attrs: nounwind + // IRINTRINSIC-NEXT: declare void @llvm.va_copy(i8* %0, i8* %1) #0 + + // IRINTRINSIC: ; Function Attrs: nounwind + // IRINTRINSIC-NEXT: declare void @llvm.va_end(i8* %0) #0 + }) + + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["VIRTUALOVERLOAD-IRINTRINSIC"]) { + // VIRTUALOVERLOAD-IRINTRINSIC: ; ModuleID = '[[ModuleName:IRIntrinsicTest]]' + // VIRTUALOVERLOAD-IRINTRINSIC-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRIntrinsicTest") + let builder = IRBuilder(module: module) + // VIRTUALOVERLOAD-IRINTRINSIC: define i32 @main() { + let main = builder.addFunction("main", + type: FunctionType([], IntType.int32)) + // VIRTUALOVERLOAD-IRINTRINSIC-NEXT: entry: + let entry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + + // VIRTUALOVERLOAD-IRINTRINSIC-NEXT: [[VAR_PTR:%[0-9]+]] = alloca i32 + let variable = builder.buildAlloca(type: IntType.int32) + + // VIRTUALOVERLOAD-IRINTRINSIC-NEXT: store i32 1, i32* [[VAR_PTR]] + builder.buildStore(IntType.int32.constant(1), to: variable) + + // VIRTUALOVERLOAD-IRINTRINSIC-NEXT: [[COPY_PTR:%[0-9]+]] = call i32* @llvm.ssa.copy.p0i32(i32* %0) + let intrinsic = module.intrinsic(Intrinsic.ID.llvm_ssa_copy, parameters: [ PointerType(pointee: IntType.int32) ])! + let cpyVar = builder.buildCall(intrinsic, args: [variable]) + + // VIRTUALOVERLOAD-IRINTRINSIC-NEXT: [[LOAD_VAR:%[0-9]+]] = load i32, i32* [[COPY_PTR]] + let loadVar = builder.buildLoad(cpyVar, type: IntType.int32) + + // VIRTUALOVERLOAD-IRINTRINSIC-NEXT: ret i32 [[LOAD_VAR]] + builder.buildRet(loadVar) + // VIRTUALOVERLOAD-IRINTRINSIC-NEXT: } + module.dump() + + // VIRTUALOVERLOAD-IRINTRINSIC: ; Function Attrs: nounwind readnone + // VIRTUALOVERLOAD-IRINTRINSIC-NEXT: declare i32* @llvm.ssa.copy.p0i32(i32* returned %0) #0 + }) + + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["INTRINSIC-FAMILY-RESOLVE"]) { + // INTRINSIC-FAMILY-RESOLVE: ; ModuleID = '[[ModuleName:IRIntrinsicTest]]' + // INTRINSIC-FAMILY-RESOLVE-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRIntrinsicTest") + let builder = IRBuilder(module: module) + // INTRINSIC-FAMILY-RESOLVE: define i32 @main() { + let main = builder.addFunction("main", + type: FunctionType([], IntType.int32)) + // INTRINSIC-FAMILY-RESOLVE-NEXT: entry: + let entry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + + let doubleAlloca = builder.buildAlloca(type: FloatType.double) + builder.buildStore(FloatType.double.constant(1.0), to: doubleAlloca) + let double = builder.buildLoad(doubleAlloca, type: FloatType.double) + + let floatAlloca = builder.buildAlloca(type: FloatType.float) + builder.buildStore(FloatType.float.constant(1.0), to: floatAlloca) + let float = builder.buildLoad(floatAlloca, type: FloatType.float) + + let halfAlloca = builder.buildAlloca(type: FloatType.half) + builder.buildStore(FloatType.half.constant(1.0), to: halfAlloca) + let half = builder.buildLoad(halfAlloca, type: FloatType.half) + + // INTRINSIC-FAMILY-RESOLVE: call double @llvm.sin.f64(double + let sinf64 = module.intrinsic(Intrinsic.ID.llvm_sin, parameters: [ FloatType.double ])! + _ = builder.buildCall(sinf64, args: [double]) + // INTRINSIC-FAMILY-RESOLVE-NEXT: call double @llvm.cos.f64(double + let cosf64 = module.intrinsic(Intrinsic.ID.llvm_cos, parameters: [ FloatType.double ])! + _ = builder.buildCall(cosf64, args: [double]) + // INTRINSIC-FAMILY-RESOLVE-NEXT: call double @llvm.sqrt.f64(double + let sqrtf64 = module.intrinsic(Intrinsic.ID.llvm_sqrt, parameters: [ FloatType.double ])! + _ = builder.buildCall(sqrtf64, args: [double]) + // INTRINSIC-FAMILY-RESOLVE-NEXT: call double @llvm.log.f64(double + let logf64 = module.intrinsic(Intrinsic.ID.llvm_log, parameters: [ FloatType.double ])! + _ = builder.buildCall(logf64, args: [double]) + + // INTRINSIC-FAMILY-RESOLVE: call float @llvm.sin.f32(float + let sinf32 = module.intrinsic(Intrinsic.ID.llvm_sin, parameters: [ FloatType.float ])! + _ = builder.buildCall(sinf32, args: [float]) + // INTRINSIC-FAMILY-RESOLVE-NEXT: call float @llvm.cos.f32(float + let cosf32 = module.intrinsic(Intrinsic.ID.llvm_cos, parameters: [ FloatType.float ])! + _ = builder.buildCall(cosf32, args: [float]) + // INTRINSIC-FAMILY-RESOLVE-NEXT: call float @llvm.sqrt.f32(float + let sqrtf32 = module.intrinsic(Intrinsic.ID.llvm_sqrt, parameters: [ FloatType.float ])! + _ = builder.buildCall(sqrtf32, args: [float]) + // INTRINSIC-FAMILY-RESOLVE-NEXT: call float @llvm.log.f32(float + let logf32 = module.intrinsic(Intrinsic.ID.llvm_log, parameters: [ FloatType.float ])! + _ = builder.buildCall(logf32, args: [float]) + + // INTRINSIC-FAMILY-RESOLVE: call half @llvm.sin.f16(half + let sinf16 = module.intrinsic(Intrinsic.ID.llvm_sin, parameters: [ FloatType.half ])! + _ = builder.buildCall(sinf16, args: [half]) + // INTRINSIC-FAMILY-RESOLVE-NEXT: call half @llvm.cos.f16(half + let cosf16 = module.intrinsic(Intrinsic.ID.llvm_cos, parameters: [ FloatType.half ])! + _ = builder.buildCall(cosf16, args: [half]) + // INTRINSIC-FAMILY-RESOLVE-NEXT: call half @llvm.sqrt.f16(half + let sqrtf16 = module.intrinsic(Intrinsic.ID.llvm_sqrt, parameters: [ FloatType.half ])! + _ = builder.buildCall(sqrtf16, args: [half]) + // INTRINSIC-FAMILY-RESOLVE-NEXT: call half @llvm.log.f16(half + let logf16 = module.intrinsic(Intrinsic.ID.llvm_log, parameters: [ FloatType.half ])! + _ = builder.buildCall(logf16, args: [half]) + + builder.buildRet(IntType.int32.zero()) + module.dump() + }) + } + + #if !os(macOS) + static var allTests = testCase([ + ("testIRIntrinsics", testIRIntrinsics), + ]) + #endif +} diff --git a/Tests/LLVMTests/IRMetadataSpec.swift b/Tests/LLVMTests/IRMetadataSpec.swift new file mode 100644 index 00000000..e2151770 --- /dev/null +++ b/Tests/LLVMTests/IRMetadataSpec.swift @@ -0,0 +1,303 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +class IRMetadataSpec : XCTestCase { + func testGlobalMetadata() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRGLOBALMETADATA"]) { + // IRGLOBALMETADATA: ModuleID = '[[ModuleName:IRGLOBALMETADATATest]]' + // IRGLOBALMETADATA-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRGLOBALMETADATATest") + let builder = IRBuilder(module: module) + let dibuilder = DIBuilder(module: module) + + let tag = module.context.metadataKind(named: "custom") + + // IRGLOBALMETADATA: @customAttachment = global i8 42, !custom !0 + let global = builder.addGlobal("customAttachment", initializer: IntType.int8.constant(42)) + + // IRGLOBALMETADATA: !0 = !DIBasicType(name: "custom_type", encoding: DW_ATE_address) + let type = dibuilder.buildBasicType(named: "custom_type", encoding: .address, flags: [], size: .zero) + global.addMetadata(type, kind: tag) + + module.dump() + }) + } + + func testInstructionMetadata() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRINSTRMETADATA"]) { + // IRINSTRMETADATA: ModuleID = '[[ModuleName:IRINSTRMETADATATest]]' + // IRINSTRMETADATA-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRINSTRMETADATATest") + let builder = IRBuilder(module: module) + let dibuilder = DIBuilder(module: module) + + let tag = module.context.metadataKind(named: "custom") + + // IRINSTRMETADATA: define i32 @test() { + let main = builder.addFunction("test", + type: FunctionType([], IntType.int32)) + // IRINSTRMETADATA-NEXT: entry: + let entry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + // IRINSTRMETADATA-NEXT: ret i32 42 + builder.buildRet(IntType.int32.constant(42)) + + let type = dibuilder.buildBasicType(named: "custom_type", encoding: .address, flags: [], size: .zero) + builder.insertBlock?.lastInstruction?.addMetadata(type, kind: tag) + // IRINSTRMETADATA-NEXT: } + + // IRINSTRMETADATA: !0 = !DIBasicType(name: "custom_type", encoding: DW_ATE_address) + module.dump() + }) + } + + func testFPMathTag() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRFPMATHMETADATA"]) { + // IRFPMATHMETADATA: ModuleID = '[[ModuleName:IRFPMathTest]]' + // IRFPMATHMETADATA-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRFPMathTest") + let builder = IRBuilder(module: module) + let MDB = MDBuilder() + XCTAssertNil(builder.defaultFloatingPointMathTag) + builder.defaultFloatingPointMathTag = MDB.buildFloatingPointMathTag(0.1) + + // IRFPMATHMETADATA: define float @test(float %0, float %1) { + let main = builder.addFunction("test", + type: FunctionType([ + FloatType.float, FloatType.float + ], FloatType.float)) + // IRFPMATHMETADATA-NEXT: entry: + let entry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + + // IRFPMATHMETADATA-NEXT: %2 = fadd float %0, %1, !fpmath !0 + let value = builder.buildAdd(main.parameters[0], main.parameters[1]) + // IRFPMATHMETADATA-NEXT: ret float %2 + builder.buildRet(value) + // IRFPMATHMETADATA-NEXT: } + + // IRFPMATHMETADATA: !0 = !{float 0x3FB99999A0000000} + module.dump() + }) + } + + func testBranchWeights() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRBWMETADATA"]) { + // IRBWMETADATA: ModuleID = '[[ModuleName:IRBWMetadataTest]]' + // IRBWMETADATA-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRBWMetadataTest") + let builder = IRBuilder(module: module) + let MDB = MDBuilder() + + // IRBWMETADATA: define float @test(i1 %0, float %1, float %2) { + let main = builder.addFunction("test", + type: FunctionType([ + IntType.int1, + FloatType.float, FloatType.float + ], FloatType.float)) + // IRBWMETADATA-NEXT: entry: + let entry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + + let thenBlock = main.appendBasicBlock(named: "then") + let elseBlock = main.appendBasicBlock(named: "else") + let mergeBB = main.appendBasicBlock(named: "merge") + let bws = MDB.buildBranchWeights([ + 1000, + 2000, + ]) + // IRBWMETADATA-NEXT: br i1 %0, label %then, label %else, !prof !0 + let branch = builder.buildCondBr(condition: main.parameters[0], then: thenBlock, else: elseBlock) + branch.addMetadata(bws, kind: .prof) + + // IRBWMETADATA: then: + // IRBWMETADATA-NEXT: %3 = fadd float %1, %2 + builder.positionAtEnd(of: thenBlock) + let opThen = builder.buildAdd(main.parameters[1], main.parameters[2]) + builder.buildBr(mergeBB) + + // IRBWMETADATA: else: + // IRBWMETADATA-NEXT: %4 = fsub float %1, %2 + builder.positionAtEnd(of: elseBlock) + let opElse = builder.buildSub(main.parameters[1], main.parameters[2]) + builder.buildBr(mergeBB) + + // IRBWMETADATA: merge: + // IRBWMETADATA-NEXT: %5 = phi float [ %3, %then ], [ %4, %else ] + builder.positionAtEnd(of: mergeBB) + let phi = builder.buildPhi(FloatType.float) + phi.addIncoming([ + (opThen, thenBlock), + (opElse, elseBlock), + ]) + + // IRBWMETADATA-NEXT: ret float %5 + builder.buildRet(phi) + // IRBWMETADATA-NEXT: } + + // IRBWMETADATA: !0 = !{!"branch_weights", i32 1000, i32 2000} + module.dump() + }) + } + + func testSimpleTBAA() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRSIMPLETBAA"]) { + // IRSIMPLETBAA: ModuleID = '[[ModuleName:IRTBAATest]]' + // IRSIMPLETBAA-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRTBAATest") + let builder = IRBuilder(module: module) + let MDB = MDBuilder() + + // IRSIMPLETBAA: define void @main() { + let F = module.addFunction("main", type: FunctionType([], VoidType())) + // IRSIMPLETBAA-NEXT: entry: + let bb = F.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: bb) + // typedef struct { + // int16_t s; + // } A; + let structTyA = StructType(elementTypes: [ + IntType.int16 + ]) + // typedef struct { + // uint32_t s; + // A a; + // } B; + let structTyB = StructType(elementTypes: [ + IntType.int32, + structTyA, + ]) + + // struct B *val = alloca(sizeof(struct B)); + // IRSIMPLETBAA-NEXT: %0 = alloca { i32, { i16 } } + let alloca = builder.buildAlloca(type: structTyB) + // IRSIMPLETBAA-NEXT: %1 = getelementptr inbounds { i32, { i16 } }, { i32, { i16 } }* %0, i64 0, i32 1, i32 0 + let field = builder.buildInBoundsGEP(alloca, type: structTyB, indices: [ + IntType.int64.constant(0), // (*this) + IntType.int32.constant(1), // .a + IntType.int32.constant(0), // .s + ]) + // B->a.s = 42 + // IRSIMPLETBAA-NEXT: store i16 42, i16* %1, align 2, !tbaa [[AccessTag:![0-9]+]] + let si = builder.buildStore(IntType.int16.constant(42), to: field) + // IRSIMPLETBAA-NEXT: ret void + builder.buildRetVoid() + // IRSIMPLETBAA-NEXT: } + + // IRSIMPLETBAA: [[AccessTag]] = !{[[BTypeNode:![0-9]+]], [[Int16Node:![0-9]+]], i64 4, i64 4} + // IRSIMPLETBAA-NEXT: [[BTypeNode]] = !{[[OmnipotentChar:![0-9]+]], i64 8, !"B", [[Int32Node:![0-9]+]], i64 0, i64 4, [[ATypeNode:![0-9]+]], i64 4, i64 2} + // IRSIMPLETBAA-NEXT: [[OmnipotentChar]] = !{[[RootNode:![0-9]+]], i64 1, !"omnipotent char"} + // IRSIMPLETBAA-NEXT: [[RootNode]] = !{!"TBAA Test Root"} + // IRSIMPLETBAA-NEXT: [[Int32Node]] = !{[[OmnipotentChar]], i64 4, !"int32_t"} + // IRSIMPLETBAA-NEXT: [[ATypeNode]] = !{[[OmnipotentChar]], i64 2, !"A", [[Int16Node]], i64 0, i64 2} + // IRSIMPLETBAA-NEXT: [[Int16Node]] = !{[[OmnipotentChar]], i64 2, !"int16_t"} + let rootMD = MDB.buildTBAARoot("TBAA Test Root") + let charMD = MDB.buildTBAATypeNode(MDString("omnipotent char"), parent: rootMD, size: .one) + let int16MD = MDB.buildTBAATypeNode(MDString("int16_t"), parent: charMD, size: Size(bits: 16)) + let int32MD = MDB.buildTBAATypeNode(MDString("int32_t"), parent: charMD, size: Size(bits: 32)) + let structAMD = MDB.buildTBAATypeNode(MDString("A"), + parent: charMD, + size: module.dataLayout.storeSize(of: structTyA), + fields: [ + .init(offset: .zero, size: Size(bits: 16), type: int16MD) + ]) + let structBMD = MDB.buildTBAATypeNode(MDString("B"), + parent: charMD, + size: module.dataLayout.storeSize(of: structTyB), + fields: [ + .init(offset: .zero, size: Size(bits: 32), type: int32MD), + .init(offset: Size(bits: 32), size: module.dataLayout.storeSize(of: structTyA), type: structAMD), + ]) + let accessTag = MDB.buildTBAAAccessTag(baseType: structBMD, accessType: int16MD, offset: Size(bits: 32), size: Size(bits: 32)) + si.addMetadata(accessTag, kind: .tbaa) + + module.dump() + try! module.verify() + }) + } + + func testMemoryTransferTBAA() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRMEMTRANSFERTBAA"]) { + // IRMEMTRANSFERTBAA: ModuleID = '[[ModuleName:IRTBAATest]]' + // IRMEMTRANSFERTBAA-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "IRTBAATest") + let builder = IRBuilder(module: module) + let MDB = MDBuilder() + + // IRMEMTRANSFERTBAA: define void @main(i8* %0) { + let F = module.addFunction("main", type: FunctionType([PointerType.toVoid], VoidType())) + // IRMEMTRANSFERTBAA-NEXT: entry: + let bb = F.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: bb) + // typedef struct { + // int16_t s; + // } A; + let structTyA = StructType(elementTypes: [ + IntType.int16 + ], isPacked: true) + // typedef struct { + // bool s; + // // Invisible padding + // unsigned pad:15; + // A a; + // } B; + let structTyB = StructType(elementTypes: [ + IntType.int1, + IntType(width: 15), + structTyA, + ], isPacked: true) + + // struct B *val = alloca(sizeof(struct B)); + // IRMEMTRANSFERTBAA-NEXT: %1 = alloca <{ i1, i15, <{ i16 }> }> + let alloca = builder.buildAlloca(type: structTyB) + // IRMEMTRANSFERTBAA-NEXT: %2 = bitcast <{ i1, i15, <{ i16 }> }>* %1 to i8* + let src = builder.buildPointerCast(of: alloca, to: PointerType(pointee: structTyB)) + // IRMEMTRANSFERTBAA-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %0, i8* align 1 %2, i32 5, i1 false), !tbaa.struct [[StructAccssTag:![0-9]+]] + let inst = builder.buildMemCpy(to: F.parameters[0], module.dataLayout.abiAlignment(of: structTyB), + from: src, module.dataLayout.abiAlignment(of: structTyB), + length: IntType.int32.constant(module.dataLayout.abiSize(of: structTyB).rawValue)) + + // IRMEMTRANSFERTBAA-NEXT: ret void + builder.buildRetVoid() + // IRMEMTRANSFERTBAA-NEXT: } + + // IRMEMTRANSFERTBAA: [[StructAccssTag]] = !{i64 0, i64 1, [[Field1AccessTag:![0-9]+]], i64 2, i64 2, [[Field2AccessTag:![0-9]+]]} + // IRMEMTRANSFERTBAA-NEXT: [[Field1AccessTag]] = !{[[BoolTypeTag:![0-9]+]], [[BoolTypeTag]], i64 0, i64 4} + // IRMEMTRANSFERTBAA-NEXT: [[BoolTypeTag]] = !{[[OmnipotentCharTypeTag:![0-9]+]], i64 1, !"bool"} + // IRMEMTRANSFERTBAA-NEXT: [[OmnipotentCharTypeTag]] = !{[[TBAARoot:![0-9]+]], i64 1, !"omnipotent char"} + // IRMEMTRANSFERTBAA-NEXT: [[TBAARoot]] = !{!"TBAA Test Root"} + // IRMEMTRANSFERTBAA-NEXT: [[Field2AccessTag]] = !{[[Int16TypeTag:![0-9]+]], [[Int16TypeTag]], i64 4, i64 2} + // IRMEMTRANSFERTBAA-NEXT: [[Int16TypeTag]] = !{[[OmnipotentCharTypeTag]], i64 2, !"int16_t"} + + // TBAA Types + let rootMD = MDB.buildTBAARoot("TBAA Test Root") + let charMD = MDB.buildTBAATypeNode(MDString("omnipotent char"), parent: rootMD, size: .one) + let int16MD = MDB.buildTBAATypeNode(MDString("int16_t"), parent: charMD, size: Size(bits: 16)) + let boolMD = MDB.buildTBAATypeNode(MDString("bool"), parent: charMD, size: Size(bits: 1)) + + // Member accesses + let field1Access = MDB.buildTBAAAccessTag(baseType: boolMD, accessType: boolMD, offset: .zero, size: Size(bits: 32)) + let field2Access = MDB.buildTBAAAccessTag(baseType: int16MD, accessType: int16MD, offset: Size(bits: 32), size: Size(bits: 16)) + let structMD = MDB.buildTBAAStructNode([ + .init(offset: .zero, size: Size(bits: 8), type: field1Access), + .init(offset: Size(bits: 16), size: Size(bits: 16), type: field2Access), + ]) + inst.addMetadata(structMD, kind: .tbaaStruct) + + module.dump() + try! module.verify() + }) + } + + #if !os(macOS) + static var allTests = testCase([ + ("testGlobalMetadata", testGlobalMetadata), + ("testFPMathTag", testFPMathTag), + ("testBranchWeights", testBranchWeights), + ("testSimpleTBAA", testSimpleTBAA), + ]) + #endif +} + diff --git a/Tests/LLVMTests/IROperationSpec.swift b/Tests/LLVMTests/IROperationSpec.swift index ea1b4e02..a3c9505c 100644 --- a/Tests/LLVMTests/IROperationSpec.swift +++ b/Tests/LLVMTests/IROperationSpec.swift @@ -12,36 +12,35 @@ class IROperationSpec : XCTestCase { let builder = IRBuilder(module: module) // BINARYOP: @a = global i32 1 - var gi1 = builder.addGlobal("a", type: IntType.int32) + let gi1 = builder.addGlobal("a", type: IntType.int32) gi1.initializer = Int32(1) // BINARYOP-NEXT: @b = global i32 1 - var gi2 = builder.addGlobal("b", type: IntType.int32) + let gi2 = builder.addGlobal("b", type: IntType.int32) gi2.initializer = Int32(1) // BINARYOP-NEXT: @c = global float 0.000000e+00 - var gf1 = builder.addGlobal("c", type: FloatType.float) + let gf1 = builder.addGlobal("c", type: FloatType.float) gf1.initializer = FloatType.float.constant(0.0) // BINARYOP-NEXT: @d = global float 0.000000e+00 - var gf2 = builder.addGlobal("d", type: FloatType.float) + let gf2 = builder.addGlobal("d", type: FloatType.float) gf2.initializer = FloatType.float.constant(0.0) // BINARYOP: define void @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: VoidType())) + type: FunctionType([], VoidType())) // BINARYOP-NEXT: entry: let entry = main.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entry) // BINARYOP-NEXT: %0 = load i32, i32* @a - let vgi1 = builder.buildLoad(gi1) + let vgi1 = builder.buildLoad(gi1, type: IntType.int32) // BINARYOP-NEXT: %1 = load i32, i32* @b - let vgi2 = builder.buildLoad(gi2) + let vgi2 = builder.buildLoad(gi2, type: IntType.int32) // BINARYOP-NEXT: %2 = load float, float* @c - let vgf1 = builder.buildLoad(gf1) + let vgf1 = builder.buildLoad(gf1, type: FloatType.float) // BINARYOP-NEXT: %3 = load float, float* @d - let vgf2 = builder.buildLoad(gf2) + let vgf2 = builder.buildLoad(gf2, type: FloatType.float) // BINARYOP-NEXT: %4 = add i32 %0, %1 _ = builder.buildBinaryOperation(.add, vgi1, vgi2) @@ -96,25 +95,24 @@ class IROperationSpec : XCTestCase { let builder = IRBuilder(module: module) // CASTOP: @a = global i32 1 - var gi = builder.addGlobal("a", type: IntType.int32) + let gi = builder.addGlobal("a", type: IntType.int32) gi.initializer = Int32(1) // CASTOP-NEXT: @f = global float 0.000000e+00 - var gf = builder.addGlobal("f", type: FloatType.float) + let gf = builder.addGlobal("f", type: FloatType.float) gf.initializer = FloatType.float.constant(0.0) // CASTOP: define void @main() { let main = builder.addFunction("main", - type: FunctionType(argTypes: [], - returnType: VoidType())) + type: FunctionType([], VoidType())) // CASTOP-NEXT: entry: let entry = main.appendBasicBlock(named: "entry") builder.positionAtEnd(of: entry) // CASTOP-NEXT: %0 = load i32, i32* @a - let vgi = builder.buildLoad(gi) + let vgi = builder.buildLoad(gi, type: IntType.int32) // CASTOP-NEXT: %1 = load float, float* @f - let vgf = builder.buildLoad(gf) + let vgf = builder.buildLoad(gf, type: FloatType.float) // CASTOP-NEXT: %2 = trunc i32 %0 to i16 _ = builder.buildCast(.trunc, value: vgi, type: IntType.int16) diff --git a/Tests/LLVMTests/IRPassManagerSpec.swift b/Tests/LLVMTests/IRPassManagerSpec.swift new file mode 100644 index 00000000..3b17c8d1 --- /dev/null +++ b/Tests/LLVMTests/IRPassManagerSpec.swift @@ -0,0 +1,383 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +class IRPassManagerSpec : XCTestCase { + func testEmptyPassPipeliner() { + let module = Module(name: "Test") + let pipeliner = PassPipeliner(module: module) + XCTAssertTrue(pipeliner.stages.isEmpty) + } + + func testAppendStages() { + let module = Module(name: "Test") + let pipeliner = PassPipeliner(module: module) + XCTAssertTrue(pipeliner.stages.isEmpty) + var rng = SystemRandomNumberGenerator() + let stageCount = (rng.next() % 25) + for i in 0.. Void = { (name) in + var fun = module.addFunction(name, type: FunctionType([], VoidType())) + fun.linkage = .external + let block = fun.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: block) + builder.buildRetVoid() + } + for name in [ "a", "b", "c", "d", "e", "f", "g" ] { + addFunction(name) + } + let pipeliner = PassPipeliner(module: module) + pipeliner.addStage("Internalize") { builder in + builder.add(.internalize { g in + print("Internalizing: \(g.name)") + return true + }) + } + + XCTAssertTrue(fileCheckOutput(of: .stdout, withPrefixes: [ "CHECK-IDEMPOTENT-INTERNALIZE" ]) { + for function in module.functions { + XCTAssertTrue(function.linkage == .external) + } + // CHECK-IDEMPOTENT-INTERNALIZE: Internalizing: a + // CHECK-IDEMPOTENT-INTERNALIZE: Internalizing: b + // CHECK-IDEMPOTENT-INTERNALIZE: Internalizing: c + // CHECK-IDEMPOTENT-INTERNALIZE: Internalizing: d + // CHECK-IDEMPOTENT-INTERNALIZE: Internalizing: e + // CHECK-IDEMPOTENT-INTERNALIZE: Internalizing: f + // CHECK-IDEMPOTENT-INTERNALIZE: Internalizing: g + pipeliner.execute() + for function in module.functions { + XCTAssertTrue(function.linkage == .external) + } + }) + } + + func testInternalizeCallback() { + let module = Module(name: "Internalize") + let builder = IRBuilder(module: module) + let addFunction: (String) -> Void = { (name) in + var fun = module.addFunction(name, type: FunctionType([], VoidType())) + fun.linkage = .external + let block = fun.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: block) + builder.buildRetVoid() + } + for name in [ "a", "b", "c", "d", "e", "f", "g" ] { + addFunction(name) + } + let pipeliner = PassPipeliner(module: module) + pipeliner.addStage("Internalize") { builder in + builder.add(.internalize { g in + print("Internalizing: \(g.name)") + return false + }) + } + + XCTAssertTrue(fileCheckOutput(of: .stdout, withPrefixes: [ "CHECK-INTERNALIZE" ]) { + for function in module.functions { + XCTAssertTrue(function.linkage == .external) + } + // CHECK-INTERNALIZE: Internalizing: a + // CHECK-INTERNALIZE: Internalizing: b + // CHECK-INTERNALIZE: Internalizing: c + // CHECK-INTERNALIZE: Internalizing: d + // CHECK-INTERNALIZE: Internalizing: e + // CHECK-INTERNALIZE: Internalizing: f + // CHECK-INTERNALIZE: Internalizing: g + pipeliner.execute() + for function in module.functions { + XCTAssertTrue(function.linkage == .internal) + } + }) + } + + private func createModule() -> Module { + let module = Module(name: "Test") + + let builder = IRBuilder(module: module) + let fun = builder.addFunction("fun", + type: FunctionType([ + IntType.int32, + IntType.int32, + ], IntType.int32)) + let entry = fun.appendBasicBlock(named: "entry") + let block1 = fun.appendBasicBlock(named: "block1") + let block2 = fun.appendBasicBlock(named: "block2") + let merge = fun.appendBasicBlock(named: "merge") + + builder.positionAtEnd(of: entry) + let val1 = builder.buildAlloca(type: IntType.int32, alignment: Alignment(4)) + let val2 = builder.buildAlloca(type: IntType.int32, alignment: Alignment(4)) + let val3 = builder.buildAlloca(type: IntType.int32, alignment: Alignment(4)) + builder.buildStore(fun.parameters[0], to: val1) + builder.buildStore(fun.parameters[1], to: val2) + builder.buildStore(IntType.int32.constant(4), to: val3) + let reloadVal1 = builder.buildLoad(val1, type: IntType.int32, alignment: Alignment(4)) + let cmpVal = builder.buildICmp(reloadVal1, IntType.int32.constant(1), .equal) + builder.buildCondBr(condition: cmpVal, then: block1, else: block2) + + builder.positionAtEnd(of: block1) + let reloadVal2 = builder.buildLoad(val1, type: IntType.int32, alignment: Alignment(4)) + let reloadVal3 = builder.buildLoad(val3, type: IntType.int32, alignment: Alignment(4)) + let sum1 = builder.buildAdd(reloadVal2, reloadVal3, overflowBehavior: .noSignedWrap) + builder.buildStore(sum1, to: val3) + builder.buildBr(merge) + + builder.positionAtEnd(of: block2) + let reloadVal4 = builder.buildLoad(val2, type: IntType.int32, alignment: Alignment(4)) + let reloadVal5 = builder.buildLoad(val3, type: IntType.int32, alignment: Alignment(4)) + let sum2 = builder.buildAdd(reloadVal4, reloadVal5, overflowBehavior: .noSignedWrap) + builder.buildStore(sum2, to: val3) + builder.buildBr(merge) + + builder.positionAtEnd(of: merge) + let reloadVal6 = builder.buildLoad(val3, type: IntType.int32, alignment: Alignment(4)) + builder.buildRet(reloadVal6) + + return module + } + + #if !os(macOS) + static var allTests = testCase([ + ("testEmptyPassPipeliner", testEmptyPassPipeliner), + ("testAppendStages", testAppendStages), + ("testAppendStandardStages", testAppendStandardStages), + ("testExecute", testExecute), + ("testExecuteWithMask", testExecuteWithMask), + ("testIdempotentInternalize", testIdempotentInternalize), + ("testInternalizeCallback", testInternalizeCallback), + ]) + #endif +} diff --git a/Tests/LLVMTests/JITSpec.swift b/Tests/LLVMTests/JITSpec.swift new file mode 100644 index 00000000..372faf53 --- /dev/null +++ b/Tests/LLVMTests/JITSpec.swift @@ -0,0 +1,262 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +// NB: Marking this function `public` is the safest way to make sure it gets +// emitted. +public func calculateFibs(_ forward: Bool) -> Double { + if forward { + return 1/109 + } else { + return 1/89 + } +} + +typealias FnPtr = @convention(c) (Bool) -> Double +private func getUnderlyingCDecl(_ function: FnPtr) -> JIT.TargetAddress { + return withoutActuallyEscaping(function) { fn in + return unsafeBitCast(fn, to: JIT.TargetAddress.self) + } +} + +class JITSpec : XCTestCase { + typealias MainFnPtr = @convention(c) () -> () + + func buildTestModule() -> Module { + let module = Module(name: "Fibonacci") + let builder = IRBuilder(module: module) + + var llvmSwiftFn = builder.addFunction( + "calculateSwiftFibs", + type: FunctionType([IntType.int1], FloatType.double) + ) + llvmSwiftFn.linkage = .external + + let function = builder.addFunction( + "calculateFibs", + type: FunctionType([IntType.int1], FloatType.double) + ) + let entryBB = function.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entryBB) + + // allocate space for a local value + let local = builder.buildAlloca(type: FloatType.double, name: "local") + + // Compare to the condition + let test = builder.buildICmp(function.parameters[0], IntType.int1.zero(), .equal) + + // Create basic blocks for "then", "else", and "merge" + let thenBB = function.appendBasicBlock(named: "then") + let elseBB = function.appendBasicBlock(named: "else") + let mergeBB = function.appendBasicBlock(named: "merge") + + builder.buildCondBr(condition: test, then: thenBB, else: elseBB) + + // MARK: Then Block + + builder.positionAtEnd(of: thenBB) + // local = 1/89, the fibonacci series (sort of) + let thenVal = FloatType.double.constant(1/89) + // Branch to the merge block + builder.buildBr(mergeBB) + + // MARK: Else Block + builder.positionAtEnd(of: elseBB) + // local = 1/109, the fibonacci series (sort of) backwards + let elseVal = FloatType.double.constant(1/109) + // Branch to the merge block + builder.buildBr(mergeBB) + + // MARK: Merge Block + + builder.positionAtEnd(of: mergeBB) + let phi = builder.buildPhi(FloatType.double, name: "phi_example") + phi.addIncoming([ + (thenVal, thenBB), + (elseVal, elseBB), + ]) + builder.buildStore(phi, to: local) + let ret = builder.buildLoad(local, type: FloatType.double, name: "ret") + builder.buildRet(ret) + + let main = builder.addFunction("main", type: FunctionType([], VoidType())) + let mainEntry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: mainEntry) + _ = builder.buildCall(llvmSwiftFn, args: [ IntType.int1.constant(1) ]) + _ = builder.buildCall(function, args: [ IntType.int1.constant(1) ]) + builder.buildRetVoid() + + return module + } + + + func testEagerIRCompilation() { + XCTAssert(fileCheckOutput(withPrefixes: ["JIT-EAGER-COMPILE"]) { + do { + let jit = try JIT(machine: TargetMachine()) + let module = buildTestModule() + + let testFuncName = jit.mangle(symbol: "calculateSwiftFibs") + var gotForced = false + _ = try jit.addEagerlyCompiledIR(module) { (name) -> JIT.TargetAddress in + gotForced = true + guard name == testFuncName else { + return JIT.TargetAddress() + } + return getUnderlyingCDecl(calculateFibs) + } + + XCTAssertFalse(gotForced) + let fibsAddr = try jit.address(of: "calculateFibs") + XCTAssertTrue(gotForced) + let fibFn = unsafeBitCast(fibsAddr, to: FnPtr.self) + // JIT-EAGER-COMPILE: 0.009174311926605505 + print(fibFn(true)) + // JIT-EAGER-COMPILE: 0.011235955056179775 + print(fibFn(false)) + } catch _ { + XCTFail() + } + }) + } + + func testLazyIRCompilation() { + XCTAssert(fileCheckOutput(withPrefixes: ["JIT-LAZY-COMPILE"]) { + do { + let jit = try JIT(machine: TargetMachine()) + let module = buildTestModule() + + let testFuncName = jit.mangle(symbol: "calculateSwiftFibs") + var gotForced = false + _ = try jit.addLazilyCompiledIR(module) { (name) -> JIT.TargetAddress in + gotForced = true + guard name == testFuncName else { + return JIT.TargetAddress() + } + return getUnderlyingCDecl(calculateFibs) + } + + XCTAssertFalse(gotForced) + let fibsAddr = try jit.address(of: "calculateFibs") + let fibFn = unsafeBitCast(fibsAddr, to: FnPtr.self) + // JIT-LAZY-COMPILE: 0.009174311926605505 + print(fibFn(true)) + XCTAssertFalse(gotForced) + // JIT-LAZY-COMPILE-NEXT: 0.011235955056179775 + print(fibFn(false)) + XCTAssertFalse(gotForced) + + let mainAddr = try jit.address(of: "main") + let mainFn = unsafeBitCast(mainAddr, to: MainFnPtr.self) + mainFn() + XCTAssertTrue(gotForced) + } catch _ { + XCTFail() + } + }) + } + + func testAddObjectFile() { + do { + let module = buildTestModule() + let targetMachine = try TargetMachine() + let objBuffer = try targetMachine.emitToMemoryBuffer(module: module, type: .object) + + let jit = JIT(machine: targetMachine) + let testFuncName = jit.mangle(symbol: "calculateSwiftFibs") + _ = try jit.addObjectFile(objBuffer) { (name) -> JIT.TargetAddress in + guard name == testFuncName else { + return JIT.TargetAddress() + } + return getUnderlyingCDecl(calculateFibs) + } + let mainAddr = try jit.address(of: "main") + XCTAssert(mainAddr != JIT.TargetAddress()) + } catch _ { + XCTFail() + } + } + + func testDirectCallbacks() { + XCTAssert(fileCheckOutput(withPrefixes: ["JIT-DIRECT-CALLBACK"]) { + do { + let jit = try JIT(machine: TargetMachine()) + + let testFuncName = jit.mangle(symbol: "calculateSwiftFibs") + let ccAddr = try jit.registerLazyCompile({ (jit) -> JIT.TargetAddress in + let sm = self.buildTestModule() + _ = try! jit.addEagerlyCompiledIR(sm) { (name) -> JIT.TargetAddress in + guard name == testFuncName else { + return JIT.TargetAddress() + } + return getUnderlyingCDecl(calculateFibs) + } + let fibsAddr = try! jit.address(of: "calculateFibs") + try! jit.setIndirectStubPointer(named: "force", address: fibsAddr) + return fibsAddr + }) + try jit.createIndirectStub(named: "force", address: ccAddr) + let fooAddr = try jit.address(of: "force") + let fooFn = unsafeBitCast(fooAddr, to: FnPtr.self) + // JIT-DIRECT-CALLBACK: 0.009174311926605505 + print(fooFn(true)) + // JIT-DIRECT-CALLBACK-NEXT: 0.011235955056179775 + print(fooFn(false)) + } catch _ { + XCTFail() + } + }) + } + + func testDirectCallBackToSwift() { + XCTAssert(fileCheckOutput(withPrefixes: ["JIT-SWIFT-CALLBACK"]) { + do { + let jit = try JIT(machine: TargetMachine()) + + let testFuncName = jit.mangle(symbol: "calculateSwiftFibs") + var gotForced = false + let ccAddr = try jit.registerLazyCompile { (jit) -> JIT.TargetAddress in + gotForced = true + let sm = self.buildTestModule() + _ = try! jit.addEagerlyCompiledIR(sm) { (name) -> JIT.TargetAddress in + guard name == testFuncName else { + return JIT.TargetAddress() + } + return getUnderlyingCDecl(calculateFibs) + } + let mainAddr = getUnderlyingCDecl(calculateFibs) + try! jit.setIndirectStubPointer(named: "force", address: mainAddr) + return mainAddr + } + + // Ensure the main entry point is compiled, causing calculateSwiftFibs + // to be lazily compiled. + try jit.createIndirectStub(named: "force", address: ccAddr) + let forceAddr = try jit.address(of: "force") + let forceFn = unsafeBitCast(forceAddr, to: FnPtr.self) + + XCTAssertFalse(gotForced) + // JIT-SWIFT-CALLBACK: 0.009174311926605505 + print(forceFn(true)) + // JIT-SWIFT-CALLBACK-NEXT: 0.011235955056179775 + print(forceFn(false)) + XCTAssertTrue(gotForced) + } catch _ { + XCTFail() + } + }) + } + + // FIXME: These tests cannot run on Linux without SEGFAULT'ing. + #if !os(macOS) + static var allTests = testCase([ + ("testEagerIRCompilation", testEagerIRCompilation), + ("testLazyIRCompilation", testLazyIRCompilation), + ("testAddObjectFile", testAddObjectFile), + ("testDirectCallbacks", testDirectCallbacks), + ("testDirectCallBackToSwift", testDirectCallBackToSwift), + ]) + #endif +} + diff --git a/Tests/LLVMTests/ModuleLinkSpec.swift b/Tests/LLVMTests/ModuleLinkSpec.swift new file mode 100644 index 00000000..b3887863 --- /dev/null +++ b/Tests/LLVMTests/ModuleLinkSpec.swift @@ -0,0 +1,66 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +class ModuleLinkSpec : XCTestCase { + func testModuleLink() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["MODULE-LINK"]) { + // MODULE-LINK: ; ModuleID = '[[ModuleName1:ModuleLinkModuleOne]]' + // MODULE-LINK-NEXT: source_filename = "[[ModuleName1]]" + let module1 = Module(name: "ModuleLinkModuleOne") + XCTAssertEqual(module1.name, "ModuleLinkModuleOne") + let builder1 = IRBuilder(module: module1) + // MODULE-LINK: define void @moduleOne() { + let mod1f = builder1.addFunction("moduleOne", + type: FunctionType([], VoidType())) + // MODULE-LINK-NEXT: entry: + let entry1 = mod1f.appendBasicBlock(named: "entry") + builder1.positionAtEnd(of: entry1) + // MODULE-LINK-NEXT: ret void + builder1.buildRetVoid() + // MODULE-LINK-NEXT: } + module1.dump() + + // MODULE-LINK: ; ModuleID = 'ModuleLinkModuleTwo' + // MODULE-LINK-NEXT: source_filename = "/Users/user/Developer/Project/file.ext" + let module2 = Module(name: "ModuleLinkModuleTwo") + XCTAssertEqual(module2.name, "ModuleLinkModuleTwo") + XCTAssertEqual(module2.sourceFileName, "ModuleLinkModuleTwo") + module2.sourceFileName = "/Users/user/Developer/Project/file.ext" + XCTAssertEqual(module2.sourceFileName, "/Users/user/Developer/Project/file.ext") + + let builder2 = IRBuilder(module: module2) + // MODULE-LINK: define void @moduleTwo() { + let mod2f = builder2.addFunction("moduleTwo", + type: FunctionType([], VoidType())) + // MODULE-LINK-NEXT: entry: + let entry2 = mod2f.appendBasicBlock(named: "entry") + builder2.positionAtEnd(of: entry2) + // MODULE-LINK-NEXT: ret void + builder2.buildRetVoid() + // MODULE-LINK-NEXT: } + module2.dump() + + XCTAssert(module1.link(module2)) + + // MODULE-LINK: ; ModuleID = '[[ModuleName1]]' + // MODULE-LINK-NEXT: source_filename = "[[ModuleName1]]" + // MODULE-LINK: define void @moduleOne() { + // MODULE-LINK-NEXT: entry: + // MODULE-LINK-NEXT: ret void + // MODULE-LINK-NEXT: } + // MODULE-LINK: define void @moduleTwo() { + // MODULE-LINK-NEXT: entry: + // MODULE-LINK-NEXT: ret void + // MODULE-LINK-NEXT: } + module1.dump() + }) + } + + #if !os(macOS) + static var allTests = testCase([ + ("testModuleLink", testModuleLink), + ]) + #endif +} diff --git a/Tests/LLVMTests/ModuleMetadataSpec.swift b/Tests/LLVMTests/ModuleMetadataSpec.swift new file mode 100644 index 00000000..973fbc53 --- /dev/null +++ b/Tests/LLVMTests/ModuleMetadataSpec.swift @@ -0,0 +1,67 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +class ModuleMetadataSpec : XCTestCase { + func testAddModuleFlags() { + XCTAssertTrue(fileCheckOutput(of: .stderr, withPrefixes: ["MODULE-FLAGS"]) { + // MODULE-FLAGS: ; ModuleID = 'ModuleFlagsTest' + let module = Module(name: "ModuleFlagsTest") + // MODULE-FLAGS: !llvm.module.flags = !{!0, !1, !2, !3, !4, !5} + + // MODULE-FLAGS: !0 = !{i32 [[ERRVAL:\d+]], !"error", i32 [[ERRVAL]]} + module.addFlag(named: "error", constant: IntType.int32.constant(1), behavior: .error) + // MODULE-FLAGS-NEXT: !1 = !{i32 [[WARNVAL:\d+]], !"warning", i32 [[WARNVAL]]} + module.addFlag(named: "warning", constant: IntType.int32.constant(2), behavior: .warning) + // MODULE-FLAGS-NEXT: !2 = !{i32 [[REQUIREVAL:\d+]], !"require", i32 [[REQUIREVAL]]} + module.addFlag(named: "require", constant: IntType.int32.constant(3), behavior: .require) + // MODULE-FLAGS-NEXT: !3 = !{i32 [[OVERRIDEVAL:\d+]], !"override", i32 [[OVERRIDEVAL]]} + module.addFlag(named: "override", constant: IntType.int32.constant(4), behavior: .override) + // MODULE-FLAGS-NEXT: !4 = !{i32 [[APPVAL:\d+]], !"append", i32 [[APPVAL]]} + module.addFlag(named: "append", constant: IntType.int32.constant(5), behavior: .append) + // MODULE-FLAGS-NEXT: !5 = !{i32 [[APPUNIQVAL:\d+]], !"appendUnique", i32 [[APPUNIQVAL]]} + module.addFlag(named: "appendUnique", constant: IntType.int32.constant(6), behavior: .appendUnique) + + module.dump() + }) + } + + func testModuleRetrieveFlags() { + let module = Module(name: "ModuleFlagsTest") + module.addFlag(named: "error", constant: IntType.int32.constant(1), behavior: .error) + module.addFlag(named: "warning", constant: IntType.int32.constant(2), behavior: .warning) + module.addFlag(named: "require", constant: IntType.int32.constant(3), behavior: .require) + module.addFlag(named: "override", constant: IntType.int32.constant(4), behavior: .override) + module.addFlag(named: "append", constant: IntType.int32.constant(5), behavior: .append) + module.addFlag(named: "appendUnique", constant: IntType.int32.constant(6), behavior: .appendUnique) + + guard let flags = module.flags else { + XCTFail() + return + } + + XCTAssertEqual(flags.count, 6) + + XCTAssertEqual(flags[0].behavior, .error) + XCTAssertEqual(flags[1].behavior, .warning) + XCTAssertEqual(flags[2].behavior, .require) + XCTAssertEqual(flags[3].behavior, .override) + XCTAssertEqual(flags[4].behavior, .append) + XCTAssertEqual(flags[5].behavior, .appendUnique) + + XCTAssertEqual(flags[0].key, "error") + XCTAssertEqual(flags[1].key, "warning") + XCTAssertEqual(flags[2].key, "require") + XCTAssertEqual(flags[3].key, "override") + XCTAssertEqual(flags[4].key, "append") + XCTAssertEqual(flags[5].key, "appendUnique") + } + + #if !os(macOS) + static var allTests = testCase([ + ("testAddModuleFlags", testAddModuleFlags), + ("testModuleRetrieveFlags", testModuleRetrieveFlags), + ]) + #endif +} diff --git a/Tests/LLVMTests/TripleSpec.swift b/Tests/LLVMTests/TripleSpec.swift new file mode 100644 index 00000000..925ae8d6 --- /dev/null +++ b/Tests/LLVMTests/TripleSpec.swift @@ -0,0 +1,856 @@ +import LLVM +import XCTest +import FileCheck +import Foundation + +class TripleSpec : XCTestCase { + func testBasicParsing() { + var T: Triple = Triple("") + XCTAssertEqual("", T.architectureName) + XCTAssertEqual("", T.vendorName) + XCTAssertEqual("", T.osName) + XCTAssertEqual("", T.environmentName) + + T = Triple("-") + XCTAssertEqual("", T.architectureName) + XCTAssertEqual("", T.vendorName) + XCTAssertEqual("", T.osName) + XCTAssertEqual("", T.environmentName) + + T = Triple("--") + XCTAssertEqual("", T.architectureName) + XCTAssertEqual("", T.vendorName) + XCTAssertEqual("", T.osName) + XCTAssertEqual("", T.environmentName) + + T = Triple("---") + XCTAssertEqual("", T.architectureName) + XCTAssertEqual("", T.vendorName) + XCTAssertEqual("", T.osName) + XCTAssertEqual("", T.environmentName) + + T = Triple("----") + XCTAssertEqual("", T.architectureName) + XCTAssertEqual("", T.vendorName) + XCTAssertEqual("", T.osName) + XCTAssertEqual("-", T.environmentName) + + T = Triple("a") + XCTAssertEqual("a", T.architectureName) + XCTAssertEqual("", T.vendorName) + XCTAssertEqual("", T.osName) + XCTAssertEqual("", T.environmentName) + + T = Triple("a-b") + XCTAssertEqual("a", T.architectureName) + XCTAssertEqual("b", T.vendorName) + XCTAssertEqual("", T.osName) + XCTAssertEqual("", T.environmentName) + + T = Triple("a-b-c") + XCTAssertEqual("a", T.architectureName) + XCTAssertEqual("b", T.vendorName) + XCTAssertEqual("c", T.osName) + XCTAssertEqual("", T.environmentName) + + T = Triple("a-b-c-d") + XCTAssertEqual("a", T.architectureName) + XCTAssertEqual("b", T.vendorName) + XCTAssertEqual("c", T.osName) + XCTAssertEqual("d", T.environmentName) + } + + func testParsedIDs() { + var T = Triple("i386-apple-darwin") + XCTAssertEqual(.x86, T.architecture) + XCTAssertEqual(.apple, T.vendor) + XCTAssertEqual(.darwin, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("i386-pc-elfiamcu") + XCTAssertEqual(.x86, T.architecture) + XCTAssertEqual(.pc, T.vendor) + XCTAssertEqual(.elfIAMCU, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("i386-pc-contiki-unknown") + XCTAssertEqual(.x86, T.architecture) + XCTAssertEqual(.pc, T.vendor) + XCTAssertEqual(.contiki, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("i386-pc-hurd-gnu") + XCTAssertEqual(.x86, T.architecture) + XCTAssertEqual(.pc, T.vendor) + XCTAssertEqual(.hurd, T.os) + XCTAssertEqual(.gnu, T.environment) + + T = Triple("x86_64-pc-linux-gnu") + XCTAssertEqual(.x86_64, T.architecture) + XCTAssertEqual(.pc, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnu, T.environment) + + T = Triple("x86_64-pc-linux-musl") + XCTAssertEqual(.x86_64, T.architecture) + XCTAssertEqual(.pc, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.musl, T.environment) + + T = Triple("powerpc-bgp-linux") + XCTAssertEqual(.ppc, T.architecture) + XCTAssertEqual(.bgp, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("powerpc-bgp-cnk") + XCTAssertEqual(.ppc, T.architecture) + XCTAssertEqual(.bgp, T.vendor) + XCTAssertEqual(.cnk, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("ppc-bgp-linux") + XCTAssertEqual(.ppc, T.architecture) + XCTAssertEqual(.bgp, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("ppc32-bgp-linux") + XCTAssertEqual(.ppc, T.architecture) + XCTAssertEqual(.bgp, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("powerpc64-bgq-linux") + XCTAssertEqual(.ppc64, T.architecture) + XCTAssertEqual(.bgq, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("ppc64-bgq-linux") + XCTAssertEqual(.ppc64, T.architecture) + XCTAssertEqual(.bgq, T.vendor) + XCTAssertEqual(.linux, T.os) + + T = Triple("powerpc-ibm-aix") + XCTAssertEqual(.ppc, T.architecture) + XCTAssertEqual(.ibm, T.vendor) + XCTAssertEqual(.aix, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("powerpc64-ibm-aix") + XCTAssertEqual(.ppc64, T.architecture) + XCTAssertEqual(.ibm, T.vendor) + XCTAssertEqual(.aix, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("powerpc-dunno-notsure") + XCTAssertEqual(.ppc, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("arm-none-none-eabi") + XCTAssertEqual(.arm, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + XCTAssertEqual(.eabi, T.environment) + + T = Triple("arm-none-linux-musleabi") + XCTAssertEqual(.arm, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.muslEABI, T.environment) + + T = Triple("armv6hl-none-linux-gnueabi") + XCTAssertEqual(.arm, T.architecture) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuEABI, T.environment) + + T = Triple("armv7hl-none-linux-gnueabi") + XCTAssertEqual(.arm, T.architecture) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuEABI, T.environment) + + T = Triple("amdil-unknown-unknown") + XCTAssertEqual(.amdil, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + + T = Triple("amdil64-unknown-unknown") + XCTAssertEqual(.amdil64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + + T = Triple("hsail-unknown-unknown") + XCTAssertEqual(.hsail, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + + T = Triple("hsail64-unknown-unknown") + XCTAssertEqual(.hsail64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + + T = Triple("sparcel-unknown-unknown") + XCTAssertEqual(.sparcel, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + + T = Triple("spir-unknown-unknown") + XCTAssertEqual(.spir, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + + T = Triple("spir64-unknown-unknown") + XCTAssertEqual(.spir64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + + T = Triple("x86_64-unknown-ananas") + XCTAssertEqual(.x86_64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.ananas, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("x86_64-unknown-cloudabi") + XCTAssertEqual(.x86_64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.cloudABI, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("x86_64-unknown-fuchsia") + XCTAssertEqual(.x86_64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.fuchsia, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("x86_64-unknown-hermit") + XCTAssertEqual(.x86_64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.hermitCore, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("wasm32-unknown-unknown") + XCTAssertEqual(.wasm32, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("wasm32-unknown-wasi-musl") + XCTAssertEqual(.wasm32, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.wasi, T.os) + XCTAssertEqual(.musl, T.environment) + + T = Triple("wasm64-unknown-unknown") + XCTAssertEqual(.wasm64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("wasm64-unknown-wasi-musl") + XCTAssertEqual(.wasm64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.wasi, T.os) + XCTAssertEqual(.musl, T.environment) + + T = Triple("avr-unknown-unknown") + XCTAssertEqual(.avr, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("avr") + XCTAssertEqual(.avr, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("lanai-unknown-unknown") + XCTAssertEqual(.lanai, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("lanai") + XCTAssertEqual(.lanai, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("amdgcn-mesa-mesa3d") + XCTAssertEqual(.amdgcn, T.architecture) + XCTAssertEqual(.mesa, T.vendor) + XCTAssertEqual(.mesa3D, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("amdgcn-amd-amdhsa") + XCTAssertEqual(.amdgcn, T.architecture) + XCTAssertEqual(.amd, T.vendor) + XCTAssertEqual(.amdHSA, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("amdgcn-amd-amdpal") + XCTAssertEqual(.amdgcn, T.architecture) + XCTAssertEqual(.amd, T.vendor) + XCTAssertEqual(.amdPAL, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("riscv32-unknown-unknown") + XCTAssertEqual(.riscv32, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.unknown, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("riscv64-unknown-linux") + XCTAssertEqual(.riscv64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("riscv64-unknown-freebsd") + XCTAssertEqual(.riscv64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.freeBSD, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("armv7hl-suse-linux-gnueabi") + XCTAssertEqual(.arm, T.architecture) + XCTAssertEqual(.suse, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnuEABI, T.environment) + + T = Triple("i586-pc-haiku") + XCTAssertEqual(.x86, T.architecture) + XCTAssertEqual(.pc, T.vendor) + XCTAssertEqual(.haiku, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("x86_64-unknown-haiku") + XCTAssertEqual(.x86_64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.haiku, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("mips-mti-linux-gnu") + XCTAssertEqual(.mips, T.architecture) + XCTAssertEqual(.mipsTechnologies, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnu, T.environment) + + T = Triple("mipsel-img-linux-gnu") + XCTAssertEqual(.mipsel, T.architecture) + XCTAssertEqual(.imaginationTechnologies, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnu, T.environment) + + T = Triple("mips64-mti-linux-gnu") + XCTAssertEqual(.mips64, T.architecture) + XCTAssertEqual(.mipsTechnologies, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnu, T.environment) + + T = Triple("mips64el-img-linux-gnu") + XCTAssertEqual(.mips64el, T.architecture) + XCTAssertEqual(.imaginationTechnologies, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnu, T.environment) + + T = Triple("mips64el-img-linux-gnuabin32") + XCTAssertEqual(.mips64el, T.architecture) + XCTAssertEqual(.imaginationTechnologies, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnuABIN32, T.environment) + + T = Triple("mips64el-unknown-linux-gnuabi64") + XCTAssertEqual(.mips64el, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnuABI64, T.environment) + T = Triple("mips64el") + XCTAssertEqual(.mips64el, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuABI64, T.environment) + + T = Triple("mips64-unknown-linux-gnuabi64") + XCTAssertEqual(.mips64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnuABI64, T.environment) + T = Triple("mips64") + XCTAssertEqual(.mips64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuABI64, T.environment) + + T = Triple("mipsisa64r6el-unknown-linux-gnuabi64") + XCTAssertEqual(.mips64el, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnuABI64, T.environment) + T = Triple("mips64r6el") + XCTAssertEqual(.mips64el, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuABI64, T.environment) + T = Triple("mipsisa64r6el") + XCTAssertEqual(.mips64el, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuABI64, T.environment) + + T = Triple("mipsisa64r6-unknown-linux-gnuabi64") + XCTAssertEqual(.mips64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnuABI64, T.environment) + T = Triple("mips64r6") + XCTAssertEqual(.mips64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuABI64, T.environment) + T = Triple("mipsisa64r6") + XCTAssertEqual(.mips64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuABI64, T.environment) + + T = Triple("mips64el-unknown-linux-gnuabin32") + XCTAssertEqual(.mips64el, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnuABIN32, T.environment) + T = Triple("mipsn32el") + XCTAssertEqual(.mips64el, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuABIN32, T.environment) + + T = Triple("mips64-unknown-linux-gnuabin32") + XCTAssertEqual(.mips64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnuABIN32, T.environment) + + T = Triple("mipsn32") + XCTAssertEqual(.mips64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuABIN32, T.environment) + + + T = Triple("mipsisa64r6el-unknown-linux-gnuabin32") + XCTAssertEqual(.mips64el, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnuABIN32, T.environment) + T = Triple("mipsn32r6el") + XCTAssertEqual(.mips64el, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuABIN32, T.environment) + + T = Triple("mipsisa64r6-unknown-linux-gnuabin32") + XCTAssertEqual(.mips64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnuABIN32, T.environment) + T = Triple("mipsn32r6") + XCTAssertEqual(.mips64, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnuABIN32, T.environment) + + T = Triple("mipsel-unknown-linux-gnu") + XCTAssertEqual(.mipsel, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnu, T.environment) + + T = Triple("mipsel") + XCTAssertEqual(.mipsel, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnu, T.environment) + + + T = Triple("mips-unknown-linux-gnu") + XCTAssertEqual(.mips, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnu, T.environment) + + T = Triple("mips") + XCTAssertEqual(.mips, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnu, T.environment) + + + T = Triple("mipsisa32r6el-unknown-linux-gnu") + XCTAssertEqual(.mipsel, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnu, T.environment) + T = Triple("mipsr6el") + XCTAssertEqual(.mipsel, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + T = Triple("mipsisa32r6el") + XCTAssertEqual(.mipsel, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnu, T.environment) + + T = Triple("mipsisa32r6-unknown-linux-gnu") + XCTAssertEqual(.mips, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnu, T.environment) + T = Triple("mipsr6") + XCTAssertEqual(.mips, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnu, T.environment) + T = Triple("mipsisa32r6") + XCTAssertEqual(.mips, T.architecture) + XCTAssertEqual(.unknown, T.vendor) + XCTAssertEqual(.gnu, T.environment) + + T = Triple("arm-oe-linux-gnueabi") + XCTAssertEqual(.arm, T.architecture) + XCTAssertEqual(.openEmbedded, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.gnuEABI, T.environment) + + T = Triple("aarch64-oe-linux") + XCTAssertEqual(.aarch64, T.architecture) + XCTAssertEqual(.openEmbedded, T.vendor) + XCTAssertEqual(.linux, T.os) + XCTAssertEqual(.unknown, T.environment) + + T = Triple("huh") + XCTAssertEqual(.unknown, T.architecture) + } + + + func testNormalization() { + XCTAssertEqual("unknown", Triple.normalize("")) + XCTAssertEqual("unknown-unknown", Triple.normalize("-")) + XCTAssertEqual("unknown-unknown-unknown", Triple.normalize("--")) + XCTAssertEqual("unknown-unknown-unknown-unknown", Triple.normalize("---")) + XCTAssertEqual("unknown-unknown-unknown-unknown-unknown", Triple.normalize("----")) + + XCTAssertEqual("a", Triple.normalize("a")) + XCTAssertEqual("a-b", Triple.normalize("a-b")) + XCTAssertEqual("a-b-c", Triple.normalize("a-b-c")) + XCTAssertEqual("a-b-c-d", Triple.normalize("a-b-c-d")) + + XCTAssertEqual("i386-b-c", Triple.normalize("i386-b-c")) + XCTAssertEqual("i386-a-c", Triple.normalize("a-i386-c")) + XCTAssertEqual("i386-a-b", Triple.normalize("a-b-i386")) + XCTAssertEqual("i386-a-b-c", Triple.normalize("a-b-c-i386")) + + XCTAssertEqual("a-pc-c", Triple.normalize("a-pc-c")) + XCTAssertEqual("unknown-pc-b-c", Triple.normalize("pc-b-c")) + XCTAssertEqual("a-pc-b", Triple.normalize("a-b-pc")) + XCTAssertEqual("a-pc-b-c", Triple.normalize("a-b-c-pc")) + + XCTAssertEqual("a-b-linux", Triple.normalize("a-b-linux")) + XCTAssertEqual("unknown-unknown-linux-b-c", Triple.normalize("linux-b-c")) + XCTAssertEqual("a-unknown-linux-c", Triple.normalize("a-linux-c")) + + XCTAssertEqual("i386-pc-a", Triple.normalize("a-pc-i386")) + XCTAssertEqual("i386-pc-unknown", Triple.normalize("-pc-i386")) + XCTAssertEqual("unknown-pc-linux-c", Triple.normalize("linux-pc-c")) + XCTAssertEqual("unknown-pc-linux", Triple.normalize("linux-pc-")) + + XCTAssertEqual("i386", Triple.normalize("i386")) + XCTAssertEqual("unknown-pc", Triple.normalize("pc")) + XCTAssertEqual("unknown-unknown-linux", Triple.normalize("linux")) + + XCTAssertEqual("x86_64-unknown-linux-gnu", Triple.normalize("x86_64-gnu-linux")) + + // Check that normalizing a permutated set of valid components returns a + // triple with the unpermuted components. + // + // We don't check every possible combination. For the set of architectures A, + // vendors V, operating systems O, and environments E, that would require |A| + // * |V| * |O| * |E| * 4! tests. Instead we check every option for any given + // slot and make sure it gets normalized to the correct position from every + // permutation. This should cover the core logic while being a tractable + // number of tests at (|A| + |V| + |O| + |E|) * 4!. + /* + let FirstArchType = ArchType.aarch64 + let FirstVendorType = VendorType.AMD + let FirstOSType = OSType.AIX + let FirstEnvType = EnvironmentType.Android + let InitialC: [String] = [ + FirstArchType.rawValue, + FirstVendorType.rawValue, + FirstOSType.rawValue, + FirstEnvType.rawValue, + ] + for Arch in ArchType.allCases.dropFirst() { + var C = InitialC + C[0] = Arch.rawValue + let E = [C[0], C[1], C[2]].joined(separator: "-") + var I = [0, 1, 2] + repeat { + XCTAssertEqual(E, Triple.normalize([C[I[0]], C[I[1]], C[I[2]]].joined(separator: "-"))) + } while nextPermutation(&I) + let F = [C[0], C[1], C[2], C[3]].joined(separator: "-") + var J = [0, 1, 2, 3] + repeat { + XCTAssertEqual(F, Triple.normalize([C[J[0]], C[J[1]], C[J[2]], C[J[3]]].joined(separator: "-"))) + } while nextPermutation(&J) + } + for Vendor in VendorType.allCases.dropFirst() { + var C = InitialC + C[1] = Vendor.rawValue + let E = [C[0], C[1], C[2]].joined(separator: "-") + var I = [0, 1, 2] + repeat { + XCTAssertEqual(E, Triple.normalize([C[I[0]], C[I[1]], C[I[2]]].joined(separator: "-"))) + } while nextPermutation(&I) + let F = [C[0], C[1], C[2], C[3]].joined(separator: "-") + var J = [0, 1, 2, 3] + repeat { + XCTAssertEqual(F, Triple.normalize([C[J[0]], C[J[1]], C[J[2]], C[J[3]]].joined(separator: "-"))) + } while nextPermutation(&J) + } + for OS in LLVM.OSType.allCases.dropFirst() { + if (OS == .Win32) { + continue + } + var C = InitialC + C[2] = OS.rawValue + let E = [C[0], C[1], C[2]].joined(separator: "-") + var I = [0, 1, 2] + repeat { + XCTAssertEqual(E, Triple.normalize([C[I[0]], C[I[1]], C[I[2]]].joined(separator: "-"))) + } while nextPermutation(&I) + let F = [C[0], C[1], C[2], C[3]].joined(separator: "-") + var J = [0, 1, 2, 3] + repeat { + XCTAssertEqual(F, Triple.normalize([C[J[0]], C[J[1]], C[J[2]], C[J[3]]].joined(separator: "-"))) + } while nextPermutation(&J) + } + for Env in EnvironmentType.allCases.dropFirst() { + var C = InitialC + C[3] = Env.rawValue + let F = [C[0], C[1], C[2], C[3]].joined(separator: "-") + var J = [0, 1, 2, 3] + repeat { + XCTAssertEqual(F, Triple.normalize([C[J[0]], C[J[1]], C[J[2]], C[J[3]]].joined(separator: "-"))) + } while nextPermutation(&J) + } + */ + + // Various real-world funky triples. The value returned by GCC's config.sub + // is given in the comment. + XCTAssertEqual("i386-unknown-windows-gnu", + Triple.normalize("i386-mingw32")) // i386-pc-mingw32 + XCTAssertEqual("x86_64-unknown-linux-gnu", + Triple.normalize("x86_64-linux-gnu")) // x86_64-pc-linux-gnu + XCTAssertEqual("i486-unknown-linux-gnu", + Triple.normalize("i486-linux-gnu")) // i486-pc-linux-gnu + XCTAssertEqual("i386-redhat-linux", + Triple.normalize("i386-redhat-linux")) // i386-redhat-linux-gnu + XCTAssertEqual("i686-unknown-linux", + Triple.normalize("i686-linux")) // i686-pc-linux-gnu + XCTAssertEqual("arm-none-unknown-eabi", + Triple.normalize("arm-none-eabi")) // arm-none-eabi + } + + func testFileFormat() { + XCTAssertEqual(.elf, Triple("i686-unknown-linux-gnu").objectFormat) + XCTAssertEqual(.elf, Triple("i686-unknown-freebsd").objectFormat) + XCTAssertEqual(.elf, Triple("i686-unknown-netbsd").objectFormat) + XCTAssertEqual(.elf, Triple("i686--win32-elf").objectFormat) + XCTAssertEqual(.elf, Triple("i686---elf").objectFormat) + + XCTAssertEqual(.machO, Triple("i686-apple-macosx").objectFormat) + XCTAssertEqual(.machO, Triple("i686-apple-ios").objectFormat) + XCTAssertEqual(.machO, Triple("i686---macho").objectFormat) + + XCTAssertEqual(.coff, Triple("i686--win32").objectFormat) + + XCTAssertEqual(.elf, Triple("i686-pc-windows-msvc-elf").objectFormat) + XCTAssertEqual(.elf, Triple("i686-pc-cygwin-elf").objectFormat) + + XCTAssertEqual(.wasm, Triple("wasm32-unknown-unknown").objectFormat) + XCTAssertEqual(.wasm, Triple("wasm64-unknown-unknown").objectFormat) + XCTAssertEqual(.wasm, Triple("wasm32-unknown-wasi-musl").objectFormat) + XCTAssertEqual(.wasm, Triple("wasm64-unknown-wasi-musl").objectFormat) + + XCTAssertEqual(.wasm, + Triple("wasm32-unknown-unknown-wasm").objectFormat) + XCTAssertEqual(.wasm, + Triple("wasm64-unknown-unknown-wasm").objectFormat) + XCTAssertEqual(.wasm, + Triple("wasm32-unknown-wasi-musl-wasm").objectFormat) + XCTAssertEqual(.wasm, + Triple("wasm64-unknown-wasi-musl-wasm").objectFormat) + + XCTAssertEqual(.xcoff, Triple("powerpc-ibm-aix").objectFormat) + XCTAssertEqual(.xcoff, Triple("powerpc64-ibm-aix").objectFormat) + XCTAssertEqual(.xcoff, Triple("powerpc---xcoff").objectFormat) + XCTAssertEqual(.xcoff, Triple("powerpc64---xcoff").objectFormat) + + let MSVCNormalized = Triple(Triple.normalize("i686-pc-windows-msvc-elf")) + XCTAssertEqual(.elf, MSVCNormalized.objectFormat) + + let GNUWindowsNormalized = Triple(Triple.normalize("i686-pc-windows-gnu-elf")) + XCTAssertEqual(.elf, GNUWindowsNormalized.objectFormat) + + let CygnusNormalised = Triple(Triple.normalize("i686-pc-windows-cygnus-elf")) + XCTAssertEqual(.elf, CygnusNormalised.objectFormat) + + let CygwinNormalized = Triple(Triple.normalize("i686-pc-cygwin-elf")) + XCTAssertEqual(.elf, CygwinNormalized.objectFormat) + } + + + func testNormalizeWindows() { + XCTAssertEqual("i686-pc-windows-msvc", Triple.normalize("i686-pc-win32")) + XCTAssertEqual("i686-unknown-windows-msvc", Triple.normalize("i686-win32")) + XCTAssertEqual("i686-pc-windows-gnu", Triple.normalize("i686-pc-mingw32")) + XCTAssertEqual("i686-unknown-windows-gnu", Triple.normalize("i686-mingw32")) + XCTAssertEqual("i686-pc-windows-gnu", Triple.normalize("i686-pc-mingw32-w64")) + XCTAssertEqual("i686-unknown-windows-gnu", Triple.normalize("i686-mingw32-w64")) + XCTAssertEqual("i686-pc-windows-cygnus", Triple.normalize("i686-pc-cygwin")) + XCTAssertEqual("i686-unknown-windows-cygnus", Triple.normalize("i686-cygwin")) + + XCTAssertEqual("x86_64-pc-windows-msvc", Triple.normalize("x86_64-pc-win32")) + XCTAssertEqual("x86_64-unknown-windows-msvc", Triple.normalize("x86_64-win32")) + XCTAssertEqual("x86_64-pc-windows-gnu", Triple.normalize("x86_64-pc-mingw32")) + XCTAssertEqual("x86_64-unknown-windows-gnu", Triple.normalize("x86_64-mingw32")) + XCTAssertEqual("x86_64-pc-windows-gnu", + Triple.normalize("x86_64-pc-mingw32-w64")) + XCTAssertEqual("x86_64-unknown-windows-gnu", + Triple.normalize("x86_64-mingw32-w64")) + + XCTAssertEqual("i686-pc-windows-elf", Triple.normalize("i686-pc-win32-elf")) + XCTAssertEqual("i686-unknown-windows-elf", Triple.normalize("i686-win32-elf")) + XCTAssertEqual("i686-pc-windows-macho", Triple.normalize("i686-pc-win32-macho")) + XCTAssertEqual("i686-unknown-windows-macho", + Triple.normalize("i686-win32-macho")) + + XCTAssertEqual("x86_64-pc-windows-elf", Triple.normalize("x86_64-pc-win32-elf")) + XCTAssertEqual("x86_64-unknown-windows-elf", + Triple.normalize("x86_64-win32-elf")) + XCTAssertEqual("x86_64-pc-windows-macho", + Triple.normalize("x86_64-pc-win32-macho")) + XCTAssertEqual("x86_64-unknown-windows-macho", + Triple.normalize("x86_64-win32-macho")) + + XCTAssertEqual("i686-pc-windows-cygnus", + Triple.normalize("i686-pc-windows-cygnus")) + XCTAssertEqual("i686-pc-windows-gnu", Triple.normalize("i686-pc-windows-gnu")) + XCTAssertEqual("i686-pc-windows-itanium", + Triple.normalize("i686-pc-windows-itanium")) + XCTAssertEqual("i686-pc-windows-msvc", Triple.normalize("i686-pc-windows-msvc")) + + XCTAssertEqual("i686-pc-windows-elf", + Triple.normalize("i686-pc-windows-elf-elf")) + } + + func testNormalizeARM() { + XCTAssertEqual("armv6-unknown-netbsd-eabi", + Triple.normalize("armv6-netbsd-eabi")) + XCTAssertEqual("armv7-unknown-netbsd-eabi", + Triple.normalize("armv7-netbsd-eabi")) + XCTAssertEqual("armv6eb-unknown-netbsd-eabi", + Triple.normalize("armv6eb-netbsd-eabi")) + XCTAssertEqual("armv7eb-unknown-netbsd-eabi", + Triple.normalize("armv7eb-netbsd-eabi")) + XCTAssertEqual("armv6-unknown-netbsd-eabihf", + Triple.normalize("armv6-netbsd-eabihf")) + XCTAssertEqual("armv7-unknown-netbsd-eabihf", + Triple.normalize("armv7-netbsd-eabihf")) + XCTAssertEqual("armv6eb-unknown-netbsd-eabihf", + Triple.normalize("armv6eb-netbsd-eabihf")) + XCTAssertEqual("armv7eb-unknown-netbsd-eabihf", + Triple.normalize("armv7eb-netbsd-eabihf")) + + XCTAssertEqual("armv7-suse-linux-gnueabihf", + Triple.normalize("armv7-suse-linux-gnueabi")) + + var T = Triple("armv6--netbsd-eabi") + XCTAssertEqual(.arm, T.architecture) + T = Triple("armv6eb--netbsd-eabi") + XCTAssertEqual(.armeb, T.architecture) + T = Triple("armv7-suse-linux-gnueabihf") + XCTAssertEqual(.gnuEABIHF, T.environment) + } + + func testParseARMArch() { + // ARM + XCTAssertEqual(.arm, Triple("arm").architecture) + XCTAssertEqual(.armeb, Triple("armeb").architecture) + + // THUMB + XCTAssertEqual(.thumb, Triple("thumb").architecture) + XCTAssertEqual(.thumbeb, Triple("thumbeb").architecture) + + // AARCH64 + XCTAssertEqual(.aarch64, Triple("arm64").architecture) + XCTAssertEqual(.aarch64, Triple("aarch64").architecture) + XCTAssertEqual(.aarch64_be, Triple("aarch64_be").architecture) + } + + #if !os(macOS) + static var allTests = testCase([ + ("testBasicParsing", testBasicParsing), + ("testParsedIDs", testParsedIDs), + ("testNormalization", testNormalization), + ("testFileFormat", testFileFormat), + ("testNormalizeWindows", testNormalizeWindows), + ("testNormalizeARM", testNormalizeARM), + ("testParseARMArch", testParseARMArch), + ]) + #endif +} + +func nextPermutation(_ arr: inout [Int]) -> Bool { + guard !arr.isEmpty else { + return false + } + + var i = arr.startIndex + i += 1; + if (i == arr.endIndex) { + return false; + } + + i = arr.endIndex; + i -= 1; + + while (true) { + let j = i; + i -= 1; + + if (arr[i] < arr[j]) { + var k = arr.endIndex + + repeat { + k -= 1 + } while !(arr[i] < arr[k]) + + + arr.swapAt(i, k) + + reverse(&arr, j, arr.endIndex); + return true; + } + + if (i == arr.startIndex) { + reverse(&arr, arr.startIndex, arr.endIndex); + return false; + } + } +} + +func reverse(_ arr: inout [Int], _ start: Int, _ end: Int) { + guard !arr.isEmpty && start < end else { + return + } + + var first = start + var last = end + repeat { + last -= 1 + arr.swapAt(first, last) + first += 1 + } while (first != end) && (first != last - 1) +} diff --git a/Tests/LLVMTests/UnitSpec.swift b/Tests/LLVMTests/UnitSpec.swift new file mode 100644 index 00000000..bb572719 --- /dev/null +++ b/Tests/LLVMTests/UnitSpec.swift @@ -0,0 +1,150 @@ +import LLVM +import XCTest +import Foundation + +class UnitSpec : XCTestCase { + func testAlign() { + let expectations: [(Size, Alignment, Size)] = [ + (Size(5), Alignment(8), Size(8)), + (Size(17), Alignment(8), Size(24)), + (Size(321), Alignment(255), Size(510)), + ] + + for (argSize, argAlign, expect) in expectations { + XCTAssertEqual(TargetData.align(argSize, to: argAlign), expect) + } + + let expectationsWithSkew: [(Size, Alignment, Size, Size)] = [ + (Size(5), Alignment(8), Size(7), Size(7)), + (Size(17), Alignment(8), Size(1), Size(17)), + (Size(321), Alignment(255), Size(42), Size(552)), + ] + + for (argSize, argAlign, argSkew, expect) in expectationsWithSkew { + XCTAssertEqual(TargetData.align(argSize, to: argAlign, skew: argSkew), expect) + } + } + + func testEmptyStructLayout() { + let mod = Module(name: "StructLayout") + + let emptyPackedStruct = StructType(elementTypes: [], isPacked: true, in: Context.global) + let emptyUnpackedStruct = StructType(elementTypes: [], isPacked: false, in: Context.global) + + let emptyPackedLayout = mod.dataLayout.layout(of: emptyPackedStruct) + XCTAssertEqual(emptyPackedLayout.alignment, Alignment.one) + XCTAssertEqual(emptyPackedLayout.size, Size.zero) + XCTAssertEqual(emptyPackedLayout.elementCount, 0) + XCTAssertFalse(emptyPackedLayout.isPadded) + let emptyUnpackedLayout = mod.dataLayout.layout(of: emptyUnpackedStruct) + XCTAssertEqual(emptyUnpackedLayout.alignment, Alignment.one) + XCTAssertEqual(emptyUnpackedLayout.size, Size.zero) + XCTAssertEqual(emptyUnpackedLayout.elementCount, 0) + XCTAssertFalse(emptyUnpackedLayout.isPadded) + } + + func testStructLayout() { + let mod = Module(name: "StructLayout") + + let packedStruct = StructType(elementTypes: [ + IntType.int1, + IntType.int8, + IntType.int1, + PointerType(pointee: IntType.int8), + ], isPacked: true, in: Context.global) + let unpackedStruct = StructType(elementTypes: [ + IntType.int1, + IntType.int8, + IntType.int1, + PointerType(pointee: IntType.int8), + ], isPacked: false, in: Context.global) + + let packedLayout = mod.dataLayout.layout(of: packedStruct) + XCTAssertEqual(packedLayout.alignment, Alignment.one) + XCTAssertEqual(packedLayout.size, Size(11)) + XCTAssertEqual(packedLayout.elementCount, 4) + XCTAssertFalse(packedLayout.isPadded) + XCTAssertEqual(packedLayout.memberOffsets, [ + Size(0), Size(1), Size(2), Size(3), + ]) + let unpackedLayout = mod.dataLayout.layout(of: unpackedStruct) + XCTAssertEqual(unpackedLayout.alignment, Alignment(8)) + XCTAssertEqual(unpackedLayout.size, Size(16)) + XCTAssertEqual(unpackedLayout.elementCount, 4) + XCTAssertTrue(unpackedLayout.isPadded) + XCTAssertEqual(unpackedLayout.memberOffsets, [ + Size(0), Size(1), Size(2), Size(8), + ]) + } + + func testStructLayoutOnMachine() { + let mod = Module(name: "StructLayout") + let aarch64 = try! TargetMachine(triple: Triple("aarch64--"), cpu: "", features: "", + optLevel: .none, relocations: .default, codeModel: .default) + mod.dataLayout = aarch64.dataLayout + XCTAssertEqual(mod.dataLayoutString, "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128") + + let packedStruct = StructType(elementTypes: [ + IntType.int1, + IntType.int8, + IntType.int1, + PointerType(pointee: IntType.int8), + ], isPacked: true, in: Context.global) + let unpackedStruct = StructType(elementTypes: [ + IntType.int1, + IntType.int8, + IntType.int1, + PointerType(pointee: IntType.int8), + ], isPacked: false, in: Context.global) + + let packedLayout64 = mod.dataLayout.layout(of: packedStruct) + XCTAssertEqual(packedLayout64.alignment, Alignment.one) + XCTAssertEqual(packedLayout64.size, Size(11)) + XCTAssertEqual(packedLayout64.elementCount, 4) + XCTAssertFalse(packedLayout64.isPadded) + XCTAssertEqual(packedLayout64.memberOffsets, [ + Size(0), Size(1), Size(2), Size(3), + ]) + let unpackedLayout64 = mod.dataLayout.layout(of: unpackedStruct) + XCTAssertEqual(unpackedLayout64.alignment, Alignment(8)) + XCTAssertEqual(unpackedLayout64.size, Size(16)) + XCTAssertEqual(unpackedLayout64.elementCount, 4) + XCTAssertTrue(unpackedLayout64.isPadded) + XCTAssertEqual(unpackedLayout64.memberOffsets, [ + Size(0), Size(1), Size(2), Size(8), + ]) + + let aarch32 = try! TargetMachine(triple: Triple("arm--"), cpu: "", features: "", + optLevel: .none, relocations: .default, codeModel: .default) + mod.dataLayout = aarch32.dataLayout + XCTAssertEqual(mod.dataLayoutString, "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64") + + let packedLayout32 = mod.dataLayout.layout(of: packedStruct) + XCTAssertEqual(packedLayout32.alignment, Alignment.one) + XCTAssertEqual(packedLayout32.size, Size(7)) + XCTAssertEqual(packedLayout32.elementCount, 4) + XCTAssertFalse(packedLayout32.isPadded) + XCTAssertEqual(packedLayout32.memberOffsets, [ + Size(0), Size(1), Size(2), Size(3), + ]) + let unpackedLayout32 = mod.dataLayout.layout(of: unpackedStruct) + XCTAssertEqual(unpackedLayout32.alignment, Alignment(4)) + XCTAssertEqual(unpackedLayout32.size, Size(8)) + XCTAssertEqual(unpackedLayout32.elementCount, 4) + XCTAssertTrue(unpackedLayout32.isPadded) + XCTAssertEqual(unpackedLayout32.memberOffsets, [ + Size(0), Size(1), Size(2), Size(4), + ]) + } + + + #if !os(macOS) + static var allTests = testCase([ + ("testAlign", testAlign), + ("testEmptyStructLayout", testEmptyStructLayout), + ("testStructLayout", testStructLayout), + ("testStructLayoutOnMachine", testStructLayoutOnMachine), + ]) + #endif +} + diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index f7bbade9..22563cda 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -4,10 +4,22 @@ import XCTest #if !os(macOS) XCTMain([ - IRBuilderSpec.allTests, + APIntSpec.allTests, + BinarySpec.allTests, + BFCSpec.allTests, ConstantSpec.allTests, + DIBuilderSpec.allTests, + FileCheckSpec.allTests, + IRBuilderSpec.allTests, IRExceptionSpec.allTests, + IRGlobalSpec.allTests, + IRIntrinsicSpec.allTests, + IRInstructionSpec.allTests, + IRMetadataSpec.allTests, IROperationSpec.allTests, - FileCheckSpec.allTests, + IRPassManagerSpec.allTests, + JITSpec.allTests, + ModuleLinkSpec.allTests, + ModuleMetadataSpec.allTests, ]) #endif diff --git a/docs/Classes.html b/docs/Classes.html index da31aefb..01130ed7 100644 --- a/docs/Classes.html +++ b/docs/Classes.html @@ -8,17 +8,26 @@ + + + +
-

Docs (100% documented)

+

LLVM 0.8 Docs (100% documented)

+

+

+ +
+

@@ -29,30 +38,93 @@
- - -
-
  • - - - Module + + + Global
    @@ -385,17 +865,17 @@

    Declaration

    -

    A Module represents the top-level structure of an LLVM program. An LLVM -module is effectively a translation unit or a collection of translation -units merged together.

    +

    A Global represents a region of memory allocated at compile time instead +of at runtime. A global variable must either have an initializer, or make +reference to an external definition that has an initializer.

    - See more + See more

    Declaration

    Swift

    -
    public final class Module: CustomStringConvertible
    +
    public final class Global : IRGlobal
    @@ -405,9 +885,9 @@

    Declaration

  • - - - Context + + + IRBuilder
    @@ -415,31 +895,144 @@

    Declaration

    -

    A Context represents execution states for the core LLVM IR system.

    +

    An IRBuilder is a helper object that generates LLVM instructions.

    - See more +

    IR builders keep track of a position (the “insertion point”) within a +module, function, or basic block and has methods to insert instructions at +that position. Other features include conveniences to insert calls to +C standard library functions like malloc and free, the creation of +global entities like © strings, and inline assembly.

    +

    Threading Considerations

    + +

    An IRBuilder object is not thread safe. It is associated with a single +module which is, in turn, associated with a single LLVM context object. +In concurrent environments, exactly one IRBuilder should be created per +thread, and that thread should be the one that ultimately created its parent +module and context. Inserting instructions into the same IR builder object +in a concurrent manner will result in malformed IR being generated in +non-deterministic ways. If concurrent codegen is needed, a separate LLVM +context, module, and IRBuilder should be created on each thread. +Once each thread has finished generating code, the resulting modules should +be merged together. See Module.link(_:) for more information.

    +

    IR Navigation

    + +

    By default, the insertion point of a builder is undefined. To move the +IR builder’s cursor, a basic block must be created, but not necessarily +inserted into a function.

    +
    let module = Module(name: "Example")
    +let builder = IRBuilder(module: module)
    +// Create a freestanding basic block and insert an `ret`
    +// instruction into it.
    +let freestanding = BasicBlock(name: "freestanding")
    +// Move the IR builder to the end of the block's instruction list.
    +builder.positionAtEnd(of: freestanding)
    +let ret = builder.buildRetVoid()
    +
    + +

    Instructions serve as a way to position the IR builder to a point before +their creation. This allows for instructions to be inserted before a +given instruction rather than at the very end of a basic block.

    +
    // Move before the `ret` instruction
    +builder.positionBefore(ret)
    +// Insert an `alloca` instruction before the `ret`.
    +let intAlloca = builder.buildAlloca(type: IntType.int8)
    +// Move before the `alloca`
    +builder.positionBefore(intAlloca)
    +// Insert an `malloc` call before the `alloca`.
    +let intMalloc = builder.buildMalloc(IntType.int8)
    +
    + +

    To insert this block into a function, see Function.append.

    + +

    Sometimes it is necessary to reset the insertion point. When the insertion +point is reset, instructions built with the IR builder are still created, +but are not inserted into a basic block. To clear the insertion point, call +IRBuilder.clearInsertionPosition().

    +

    Building LLVM IR

    + +

    All functions that build instructions are prefixed with build. Invoking +these functions inserts the appropriate LLVM instruction at the insertion +point, assuming it points to a valid location.

    +
    let module = Module(name: "Example")
    +let builder = IRBuilder(module: module)
    +let fun = builder.addFunction("test",
    +                              type: FunctionType([
    +                                      IntType.int8,
    +                                      IntType.int8,
    +                              ], FloatType.float))
    +let entry = fun.appendBasicBlock(named: "entry")
    +// Set the insertion point to the entry block of this function
    +builder.positionAtEnd(of: entry)
    +// Build an `add` instruction at the insertion point
    +let result = builder.buildAdd(fun.parameters[0], fun.parameters[1])
    +
    +

    Customizing LLVM IR

    + +

    To be well-formed, certain instructions may involve more setup than just +being built. In such cases, LLVMSwift will yield a specific instance of +IRInstruction that will allow for this kind of configuration.

    + +

    A prominent example of this is the PHI node. Building a PHI node produces +an empty PHI node - this is not a well-formed instruction. A PHI node must +have its incoming basic blocks attached. To do so, PhiNode.addIncoming(_:) +is called with a list of pairs of incoming values and their enclosing +basic blocks.

    +
    // Build a function that selects one of two floating parameters based
    +// on a given boolean value.
    +let module = Module(name: "Example")
    +let builder = IRBuilder(module: module)
    +let select = builder.addFunction("select",
    +                                 type: FunctionType([
    +                                         IntType.int1,
    +                                         FloatType.float,
    +                                         FloatType.float,
    +                                 ], FloatType.float))
    +let entry = select.appendBasicBlock(named: "entry")
    +builder.positionAtEnd(of: entry)
    +
    +let thenBlock = select.appendBasicBlock(named: "then")
    +let elseBlock = select.appendBasicBlock(named: "else")
    +let mergeBB = select.appendBasicBlock(named: "merge")
    +let branch = builder.buildCondBr(condition: select.parameters[0],
    +                                 then: thenBlock,
    +                                 else: elseBlock)
    +builder.positionAtEnd(of: thenBlock)
    +let opThen = builder.buildAdd(select.parameters[1], select.parameters[2])
    +builder.buildBr(mergeBB)
    +builder.positionAtEnd(of: elseBlock)
    +let opElse = builder.buildSub(select.parameters[1], select.parameters[2])
    +builder.buildBr(mergeBB)
    +builder.positionAtEnd(of: mergeBB)
    +
    +// Build the PHI node
    +let phi = builder.buildPhi(FloatType.float)
    +// Attach the incoming blocks.
    +phi.addIncoming([
    +  (opThen, thenBlock),
    +  (opElse, elseBlock),
    +])
    +builder.buildRet(phi)
    +
    + + See more

    Declaration

    Swift

    -
    public class Context
    +
    public class IRBuilder
  • -
-
-
-
  • @@ -447,33 +1040,145 @@

    Declaration

    -

    An IRBuilder is a helper object that generates LLVM instructions. IR -Builders keep track of a position within a function or basic block and has -methods to insert instructions at that position.

    +

    Represents a temporary metadata node.

    - See more +

    Temporary metadata nodes aid in the construction of cyclic metadata. The +typical construction pattern is usually as follows:

    +
    // Allocate a temporary temp node
    +let temp = TemporaryMDNode(in: context, operands: [])
    +// Prepare the operands to the metadata node...
    +var ops = [IRMetadata]()
    +// ...
    +// Create the real node
    +let root = MDNode(in: context, operands: ops)
    +
    + +

    At this point we have the following metadata structure:

    +
    //   !0 = metadata !{}            <- temp
    +//   !1 = metadata !{metadata !0} <- root
    +// Replace the temp operand with the root node
    +
    + +

    The knot is tied by RAUW'ing the temporary node:

    +
    temp.replaceAllUses(with: root)
    +// We now have
    +//   !1 = metadata !{metadata !1} <- self-referential root
    +
    +
    +

    Warning

    + It is critical that temporary metadata nodes be “RAUW’d” +(replace-all-uses-with) before the metadata graph is finalized. After +that time, all remaining temporary metadata nodes will become unresolved +metadata. + +
    + + See more

    Declaration

    Swift

    -
    public class IRBuilder
    +
    public class TemporaryMDNode : IRMetadata
  • -
-
-
-
  • - + + + Intrinsic + +
    +
    +
    +
    +
    +
    +

    An Intrinsic represents an intrinsic known to LLVM.

    + +

    Intrinsic functions have well known names and semantics and are required to +follow certain restrictions. Overall, these intrinsics represent an +extension mechanism for the LLVM language that does not require changing all +of the transformations in LLVM when adding to the language (or the bitcode +reader/writer, the parser, etc…).

    + +

    Intrinsic function names must all start with an llvm. prefix. This prefix +is reserved in LLVM for intrinsic names; thus, function names may not begin +with this prefix. Intrinsic functions must always be external functions: you +cannot define the body of intrinsic functions. Intrinsic functions may only +be used in call or invoke instructions: it is illegal to take the address of +an intrinsic function.

    + +

    Some intrinsic functions can be overloaded, i.e., the intrinsic represents a +family of functions that perform the same operation but on different data +types. Because LLVM can represent over 8 million different integer types, +overloading is used commonly to allow an intrinsic function to operate on +any integer type. One or more of the argument types or the result type can +be overloaded to accept any integer type. Argument types may also be defined +as exactly matching a previous argument’s type or the result type. This +allows an intrinsic function which accepts multiple arguments, but needs all +of them to be of the same type, to only be overloaded with respect to a +single argument or the result.

    + +

    Overloaded intrinsics will have the names of its overloaded argument types +encoded into its function name, each preceded by a period. Only those types +which are overloaded result in a name suffix. Arguments whose type is +matched against another type do not. For example, the llvm.ctpop function +can take an integer of any width and returns an integer of exactly the same +integer width. This leads to a family of functions such as +i8 @llvm.ctpop.i8(i8 %val) and i29 @llvm.ctpop.i29(i29 %val). Only one +type, the return type, is overloaded, and only one type suffix is required. +Because the argument’s type is matched against the return type, it does not +require its own name suffix.

    +

    Dynamic Member Lookup For Intrinsics

    + +

    This library provides a dynamic member lookup facility for retrieving +intrinsic selectors. For any LLVM intrinsic selector of the form +llvm.foo.bar.baz, the name of the corresponding dynamic member is that +name with any dots replaced by underscores.

    + +

    For example:

    +
    llvm.foo.bar.baz -> Intrinsic.ID.llvm_foo_bar_baz
    +llvm.stacksave -> Intrinsic.ID.llvm_stacksave
    +llvm.x86.xsave64 -> Intrinsic.ID.llvm_x86_xsave64
    +
    + +

    Any existing underscores do not need to be replaced, e.g. +llvm.va_copy becomes Intrinsic.ID.llvm_va_copy.

    + +

    For overloaded intrinsics, the non-overloaded prefix excluding the explicit +type parameters is used and normalized according to the convention above.

    + +

    For example:

    +
    llvm.sinf64 -> Intrinsic.ID.llvm_sin
    +llvm.memcpy.p0i8.p0i8.i32 -> Intrinsic.ID.llvm_memcpy
    +llvm.bswap.v4i32 -> Intrinsic.ID.llvm_bswap
    +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public class Intrinsic : Function
    + +
    +
    +
    +
    +
  • +
  • +
    + + - JIT + JIT
    @@ -486,29 +1191,57 @@

    Declaration

    and return the value the function generated, allowing you to write interactive programs that will run as soon as they are compiled.

    +

    The JIT is fundamentally lazy, and allows control over when and how symbols +are resolved.

    + See more

    Declaration

    Swift

    -
    public final class JIT
    +
    public final class JIT
- - -
-
  • - + + + MDBuilder + +
    +
    +
    +
    +
    +
    +

    An MDBuilder object provides a convenient way to build common metadata +nodes.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public final class MDBuilder
    + +
    +
    +
    +
    +
  • +
  • +
    @@ -533,23 +1266,169 @@

    Declaration

    Declaration

    Swift

    -
    public class MemoryBuffer: Sequence
    +
    public class MemoryBuffer : Sequence
    + +
    +
    + +
+ +
  • +
    + + + + Module + +
    +
    +
    +
    +
    +
    +

    A Module represents the top-level structure of an LLVM program. An LLVM +module is effectively a translation unit or a collection of translation +units merged together.

    + +

    LLVM programs are composed of Modules consisting of functions, global +variables, symbol table entries, and metadata. Modules may be combined +together with the LLVM linker, which merges function (and global variable) +definitions, resolves forward declarations, and merges symbol table entries.

    +

    Creating a Module

    + +

    A module can be created using init(name:context:). +Note that the default target triple is bare metal and there is no default data layout. +If you require these to be specified (e.g. to increase the correctness of default alignment values), +be sure to set them yourself.

    +
    if let machine = try? TargetMachine() {
    +    module.targetTriple = machine.triple
    +    module.dataLayout = machine.dataLayout
    +}
    +
    +

    Verifying a Module

    + +

    A module naturally grows to encompass a large amount of data during code +generation. To verify that the module is well-formed and suitable for +submission to later phases of LLVM, call Module.verify(). If the module +does not pass verification, an error describing the cause will be thrown.

    +
    let module = Module(name: "Example")
    +let builder = IRBuilder(module: module)
    +let main = builder.addFunction("main",
    +                               type: FunctionType([], VoidType()))
    +let entry = main.appendBasicBlock(named: "entry")
    +builder.positionAtEnd(of: entry)
    +builder.buildRet(main.address(of: entry)!)
    +
    +try module.verify()
    +// The following error is thrown:
    +//   module did not pass verification: blockaddress may not be used with the entry block!
    +//   Found return instr that returns non-void in Function of void return type!
    +
    + +

    The built-in verifier attempts to be correct at the cost of completeness. +For strictest checking, invoke the lli tool on any IR that is generated.

    +

    Threading Considerations

    + +

    A module value is associated with exactly one LLVM context. That context, +and its creating thread, must be used to access and mutate this module as +LLVM provides no locking or atomicity guarantees.

    +

    Printing The Contents of a Module

    + +

    The contents of a module are mostly machine-independent. It is often useful +while debugging to view this machine-independent IR. A module responds to +Module.dump() by printing this representation to standard output. To +dump the module to a file, use Module.print(to:). In general, a module +must be associated with a TargetMachine and a target environment for its +contents to be fully useful for export to later file formats such as object +files or bitcode. See TargetMachine.emitToFile(module:type:path) for more +details.

    +

    Module Flags

    + +

    To convey information about a module to LLVM’s various subsystems, a module +may have flags attached. These flags are keyed by global strings, and +attached as metadata to the module with the privileged llvm.module.flags +metadata identifier. Certain flags have hard-coded meanings in LLVM such as +the Objective-C garbage collection flags or the linker options flags. Most +other flags are stripped from any resulting object files.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public final class Module : CustomStringConvertible
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + NamedMetadata + +
    +
    +
    +
    +
    +
    +

    A NamedMetadata object represents a module-level metadata value identified +by a user-provided name. Named metadata is generated lazily when operands +are attached.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public class NamedMetadata
  • - - -
    -
    • - + + + BinaryFile + +
      +
      +
      +
      +
      +
      +

      A BinaryFile is a (mostly) architecture-independent representation of an +in-memory image file.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public class BinaryFile
      + +
      +
      +
      +
      +
    • +
    • +
      @@ -565,7 +1444,35 @@

      Declaration

      Declaration

      Swift

      -
      public class ObjectFile
      +
      public class ObjectFile : BinaryFile
      + +
      +
      + +
    + +
  • + +
    +
    +
    +
    +
    +

    An in-memory representation of a Mach-O universal binary file.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public final class MachOUniversalBinaryFile : BinaryFile
    @@ -575,9 +1482,9 @@

    Declaration

  • @@ -593,7 +1500,7 @@

    Declaration

    Declaration

    Swift

    -
    public class SectionSequence: Sequence
    +
    public class SectionSequence : Sequence
    @@ -603,9 +1510,9 @@

    Declaration

  • @@ -621,7 +1528,7 @@

    Declaration

    Declaration

    Swift

    -
    public class RelocationSequence: Sequence
    +
    public class RelocationSequence : Sequence
    @@ -631,9 +1538,9 @@

    Declaration

  • @@ -649,23 +1556,19 @@

    Declaration

    Declaration

    Swift

    -
    public class SymbolSequence: Sequence
    +
    public class SymbolSequence : Sequence
  • - - -
    -
    • @@ -683,23 +1586,57 @@

      Declaration

      Declaration

      Swift

      -
      public class FunctionPassManager
      +
      @available(*, deprecated, message: "Use the PassPipeliner instead")
      +public class FunctionPassManager
    - - -
    -
    • - + + + PassPipeliner + +
      +
      +
      +
      +
      +
      +

      Implements a pass manager, pipeliner, and executor for a set of +user-provided optimization passes.

      + +

      A PassPipeliner handles the creation of a related set of optimization +passes called a “pipeline”. Grouping passes is done for multiple reasons, +chief among them is that optimizer passes are extremely sensitive to their +ordering relative to other passes. In addition, pass groupings allow for +the clean segregation of otherwise unrelated passes. For example, a +pipeline might consist of “mandatory” passes such as Jump Threading, LICM, +and DCE in one pipeline and “diagnostic” passes in another.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public final class PassPipeliner
      + +
      +
      +
      +
      +
    • +
    • +
      @@ -717,23 +1654,19 @@

      Declaration

      Declaration

      Swift

      -
      public class TargetData
      +
      public class TargetData
    - - -
    -
    • - + - Target + Target
      @@ -750,7 +1683,7 @@

      Declaration

      Declaration

      Swift

      -
      public class Target
      +
      public class Target
      @@ -760,9 +1693,9 @@

      Declaration

    • @@ -780,7 +1713,7 @@

      Declaration

      Declaration

      Swift

      -
      public class TargetMachine
      +
      public class TargetMachine
      @@ -792,8 +1725,8 @@

      Declaration

    diff --git a/docs/docsets/.docset/Contents/Resources/Documents/Structs/VectorType.html b/docs/Classes/AttachedMetadata.html similarity index 51% rename from docs/docsets/.docset/Contents/Resources/Documents/Structs/VectorType.html rename to docs/Classes/AttachedMetadata.html index c64baa87..cb959b68 100644 --- a/docs/docsets/.docset/Contents/Resources/Documents/Structs/VectorType.html +++ b/docs/Classes/AttachedMetadata.html @@ -1,27 +1,35 @@ - VectorType Struct Reference + AttachedMetadata Class Reference + + + - - + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    diff --git a/docs/Classes/AttachedMetadata/Entry.html b/docs/Classes/AttachedMetadata/Entry.html new file mode 100644 index 00000000..7adf178c --- /dev/null +++ b/docs/Classes/AttachedMetadata/Entry.html @@ -0,0 +1,656 @@ + + + + Entry Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    Entry

    +
    +
    + +
    public struct Entry
    + +
    +
    +

    Represents an entry in the module flags structure.

    + +
    +
    +
    +
      +
    • +
      + + + + kind + +
      +
      +
      +
      +
      +
      +

      The metadata kind associated with this global metadata.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var kind: UInt32 { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + metadata + +
      +
      +
      +
      +
      +
      +

      The metadata value associated with this entry.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var metadata: IRMetadata { get }
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/AttachedMetadata/PinnedKind.html b/docs/Classes/AttachedMetadata/PinnedKind.html new file mode 100644 index 00000000..cf6dd781 --- /dev/null +++ b/docs/Classes/AttachedMetadata/PinnedKind.html @@ -0,0 +1,1861 @@ + + + + PinnedKind Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    PinnedKind

    +
    +
    + +
    public enum PinnedKind : UInt32
    + +
    +
    +

    Metadata kinds that are known to LLVM.

    + +
    +
    +
    +
      +
    • +
      + + + + dbg + +
      +
      +
      +
      +
      +
      +

      Debug information metadata.

      + +

      dbg metadata is used to record primary debugging source-level +debugging information for values and functions.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case dbg = 0
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + tbaa + +
      +
      +
      +
      +
      +
      +

      Type Based Alias Analysis metadata.

      + +

      In LLVM IR, memory does not have types, so LLVM’s own type system is not +suitable for doing type based alias analysis (TBAA). Instead, metadata +is added to the IR to describe a type system of a higher level language. +This can be used to implement C/C++ strict type aliasing rules, but it +can also be used to implement custom alias analysis behavior for other +languages.

      + +

      To read more about how to do TBAA in LLVM, see the +Language Reference.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case tbaa = 1
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + prof + +
      +
      +
      +
      +
      +
      +

      Profiling metadata.

      + +

      prof metadata is used to record profile data in the IR. The first +operand of the metadata node indicates the profile metadata type. There +are currently 3 types: branch_weights, function_entry_count, +and VP.

      + +

      Branch weight metadata attached to a branch, select, switch or +call instruction represents the likeliness of the associated branch +being taken.

      + +

      Function entry count metadata can be attached to function definitions to +record the number of times the function is called. Used with +block frequency information, it is also used to derive the basic block +profile count.

      + +

      VP (value profile) metadata can be attached to instructions that have +value profile information. Currently this is indirect calls (where it +records the hottest callees) and calls to memory intrinsics such as +memcpy, memmove, and memset (where it records the hottest byte +lengths).

      + +

      Each VP metadata node contains the “VP” string, then an unsigned 32-bit +value for the value profiling kind, an unsigned 64-bit value for the +total number of times the instruction is executed, followed by an +unsigned 64-bit value and execution count pairs. The value profiling +kind is 0 for indirect call targets and 1 for memory operations. For +indirect call targets, each profile value is a hash of the callee +function name, and for memory operations each value is the byte length.

      + +

      Note that the value counts do not need to add up to the total count +listed in the third operand (in practice only the top hottest values +are tracked and reported).

      + +

      For example:

      +
      call void %f(), !prof !1
      +!1 = !{!"VP", i32 0, i64 1600, i64 7651369219802541373, i64 1030, i64 -4377547752858689819, i64 410}
      +
      + +

      Note that the VP type is 0 (the second operand), which indicates this is +an indirect call value profile data. The third operand indicates that +the indirect call executed 1600 times. The 4th and 6th operands give the +hashes of the 2 hottest target functions’ names (this is the same hash +used to represent function names in the profile database), and the 5th +and 7th operands give the execution count that each of the respective +prior target functions was called.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case prof = 2
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + fpmath + +
      +
      +
      +
      +
      +
      +

      Floating-point math metadata.

      + +

      fpmath metadata may be attached to any instruction of floating-point +type. It can be used to express the maximum acceptable error in the +result of that instruction, in ULPs, thus potentially allowing the +compiler to use a more efficient but less accurate method of computing +it. ULP is defined as follows:

      + +

      If x is a real number that lies between two finite consecutive +floating-point numbers a and b, without being equal to one of them, +then ulp(x) = |b - a|, otherwise ulp(x) is the distance between the +two non-equal finite floating-point numbers nearest x. +Moreover, ulp(NaN) is NaN.

      + +

      The metadata node shall consist of a single positive float type number +representing the maximum relative error, for example:

      +
      !0 = !{ float 2.5 } ; maximum acceptable inaccuracy is 2.5 ULPs
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case fpmath = 3
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + range + +
      +
      +
      +
      +
      +
      +

      Range metadata.

      + +

      Range metadata may be attached only to load, call and invoke of integer +types. It expresses the possible ranges the loaded value or the value +returned by the called function at this call site is in. If the loaded +or returned value is not in the specified range, the behavior is +undefined. The ranges are represented with a flattened list of integers. +The loaded value or the value returned is known to be in the union of +the ranges defined by each consecutive pair. Each pair has the +following properties:

      + +
        +
      • The type must match the type loaded by the instruction.
      • +
      • The pair a,b represents the range [a,b).
      • +
      • Both a and b are constants.
      • +
      • The range is allowed to wrap.
      • +
      • The range should not represent the full or empty set. +That is, a != b.
      • +
      • In addition, the pairs must be in signed order of the lower bound and +they must be non-contiguous.
      • +
      + +

      For example:

      +
      %a = load i8, i8* %x, align 1, !range !0 ; Can only be 0 or 1
      +%b = load i8, i8* %y, align 1, !range !1 ; Can only be 255 (-1), 0 or 1
      +%c = call i8 @foo(),       !range !2 ; Can only be 0, 1, 3, 4 or 5
      +%d = invoke i8 @bar() to label %cont
      +unwind label %lpad, !range !3 ; Can only be -2, -1, 3, 4 or 5
      +...
      +!0 = !{ i8 0, i8 2 }
      +!1 = !{ i8 255, i8 2 }
      +!2 = !{ i8 0, i8 2, i8 3, i8 6 }
      +!3 = !{ i8 -2, i8 0, i8 3, i8 6 }
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case range = 4
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + tbaaStruct + +
      +
      +
      +
      +
      +
      +

      Type Based Alias Analysis struct metadata.

      + +

      The llvm.memcpy.* family of instrinsics is often used to implement +aggregate assignment operations in C and similar languages, however it +is defined to copy a contiguous region of memory, which is more than +strictly necessary for aggregate types which contain holes due to +padding. Also, it doesn’t contain any TBAA information about the fields +of the aggregate.

      + +

      tbaa.struct metadata can describe which memory subregions in a +memcpy are padding and what the TBAA tags of the struct are.

      + +

      The current metadata format is very simple. tbaa.struct metadata nodes +are a list of operands which are in conceptual groups of three. For each +group of three, the first operand gives the byte offset of a field in +bytes, the second gives its size in bytes, and the third gives its +tbaa tag. e.g.:

      +
      !4 = !{ i64 0, i64 4, !1, i64 8, i64 4, !2 }
      +
      + +

      This describes a struct with two fields: The first is at offset 0 bytes +with size 4 bytes, and has tbaa tag !1. The second is at offset 8 +bytes and has size 4 bytes and has tbaa tag !2.

      + +

      Note that the fields need not be contiguous. In this example, there is a +4 byte gap between the two fields. This gap represents padding which +does not carry useful data and need not be preserved.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case tbaaStruct = 5
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + invariantLoad + +
      +
      +
      +
      +
      +
      +

      Load addreess invariance metadata.

      + +

      If a load instruction tagged with the invariant.load metadata is +executed, the optimizer may assume the memory location referenced by the +load contains the same value at all points in the program where the +memory location is known to be dereferenceable; otherwise, the +behavior is undefined.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case invariantLoad = 6
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + aliasScope + +
      +
      +
      +
      +
      +
      +

      Alias scope metadata.

      + +

      alias.scope metadata provide the ability to specify generic noalias +memory-access sets. This means that some collection of memory access +instructions (loads, stores, memory-accessing calls, etc.) that carry +noalias metadata can specifically be specified not to alias with some +other collection of memory access instructions that carry alias.scope +metadata. Each type of metadata specifies a list of scopes where each +scope has an id and a domain.

      + +

      When evaluating an aliasing query, if for some domain, the set of scopes +with that domain in one instruction’s alias.scope list is a subset of +(or equal to) the set of scopes for that domain in another instruction’s +noalias list, then the two memory accesses are assumed not to alias.

      + +

      Because scopes in one domain don’t affect scopes in other domains, +separate domains can be used to compose multiple independent noalias +sets. This is used for example during inlining. As the noalias function +parameters are turned into noalias scope metadata, a new domain is used +every time the function is inlined.

      + +

      The metadata identifying each domain is itself a list containing one or +two entries. The first entry is the name of the domain. Note that if the +name is a string then it can be combined across functions and +translation units. A self-reference can be used to create globally +unique domain names. A descriptive string may optionally be provided as +a second list entry.

      + +

      The metadata identifying each scope is also itself a list containing two +or three entries. The first entry is the name of the scope. Note that if +the name is a string then it can be combined across functions and +translation units. A self-reference can be used to create globally +unique scope names. A metadata reference to the scope’s domain is the +second entry. A descriptive string may optionally be provided as a third +list entry.

      + +

      For example:

      +
      ; Two scope domains:
      +!0 = !{!0}
      +!1 = !{!1}
      +
      +; Some scopes in these domains:
      +!2 = !{!2, !0}
      +!3 = !{!3, !0}
      +!4 = !{!4, !1}
      +
      +; Some scope lists:
      +!5 = !{!4} ; A list containing only scope !4
      +!6 = !{!4, !3, !2}
      +!7 = !{!3}
      +
      +; These two instructions don't alias:
      +%0 = load float, float* %c, align 4, !alias.scope !5
      +store float %0, float* %arrayidx.i, align 4, !noalias !5
      +
      +; These two instructions also don't alias (for domain !1, the set of scopes
      +; in the !alias.scope equals that in the !noalias list):
      +%2 = load float, float* %c, align 4, !alias.scope !5
      +store float %2, float* %arrayidx.i2, align 4, !noalias !6
      +
      +; These two instructions may alias (for domain !0, the set of scopes in
      +; the !noalias list is not a superset of, or equal to, the scopes in the
      +; !alias.scope list):
      +%2 = load float, float* %c, align 4, !alias.scope !6
      +store float %0, float* %arrayidx.i, align 4, !noalias !7
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case aliasScope = 7
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + noalias + +
      +
      +
      +
      +
      +
      +

      No-alias metadata.

      + +

      noalias metadata provide the ability to specify generic noalias +memory-access sets. This means that some collection of memory access +instructions (loads, stores, memory-accessing calls, etc.) that carry +noalias metadata can specifically be specified not to alias with some +other collection of memory access instructions that carry alias.scope +metadata. Each type of metadata specifies a list of scopes where each +scope has an id and a domain.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case noalias = 8
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + nontemporal + +
      +
      +
      +
      +
      +
      +

      Temporal metadata.

      + +

      The existence of the !nontemporal metadata on the instruction tells the +optimizer and code generator that this load is not expected to be reused +in the cache. The code generator may select special instructions to save +cache bandwidth, such as the MOVNT instruction on x86.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case nontemporal = 9
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + memParallelLoopAccess + +
      +
      +
      +
      +
      +
      +

      Loop memory access metadata.

      + +

      If certain memory accesses within a loop are independent of each other +(that is, they have no loop-carried dependencies), and if these are the +only accesses in the loop, then tagging load/store instructions with +llvm.mem.parallel_loop_access signals to the optimizer that those +accesses can be vectorized.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case memParallelLoopAccess = 10
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + nonnull + +
      +
      +
      +
      +
      +
      +

      Non-null metadata.

      + +

      This indicates that the parameter or return pointer is not null. This +attribute may only be applied to pointer typed parameters. This is not +checked or enforced by LLVM; if the parameter or return pointer is null, +the behavior is undefined.

      + +

      Note that the concept of a “null” pointer is address space dependent. it is +not necessarily the 0 bit-pattern.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case nonnull = 11
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + dereferenceable + +
      +
      +
      +
      +
      +
      +

      Dereferenceable metadata.

      + +

      This indicates that the parameter or return pointer is dereferenceable. +This attribute may only be applied to pointer typed parameters. A +pointer that is dereferenceable can be loaded from speculatively without +a risk of trapping. The number of bytes known to be dereferenceable must +be provided in parentheses. It is legal for the number of bytes to be +less than the size of the pointee type. The nonnull attribute does not +imply dereferenceability (consider a pointer to one element past the end +of an array), however dereferenceable does imply nonnull in +the default address space.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case dereferenceable = 12
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + dereferenceableOrNull + +
      +
      +
      +
      +
      +
      +

      Dereferenceable or null metadata.

      + +

      This indicates that the parameter or return value isn’t both non-null +and non-dereferenceable (up to a given number of bytes) at the same +time. All non-null pointers tagged with dereferenceable_or_null are +dereferenceable. For address space 0, dereferenceable_or_null +implies that a pointer is exactly one of dereferenceable or null, +and in other address spaces dereferenceable_or_null implies that a +pointer is at least one of dereferenceable or null (i.e. it may be +both null and dereferenceable). This attribute may only be applied +to pointer typed parameters.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case dereferenceableOrNull = 13
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + makeImplicit + +
      +
      +
      +
      +
      +
      +

      Implicit checks metadata.

      + +

      Making null checks implicit is an aggressive optimization, and it can be +a net performance pessimization if too many memory operations end up +faulting because of it. A language runtime typically needs to ensure +that only a negligible number of implicit null checks actually fault +once the application has reached a steady state. A standard way of doing +this is by healing failed implicit null checks into explicit null checks +via code patching or recompilation. It follows that there are two +requirements an explicit null check needs to satisfy for it to be +profitable to convert it to an implicit null check:

      + +
        +
      • The case where the pointer is actually null (i.e. the “failing” case) +is extremely rare.
      • +
      • The failing path heals the implicit null check into an explicit null +check so that the application does not repeatedly page fault.
      • +
      + +

      The frontend is expected to mark branches that satisfy both conditions +using a make.implicit metadata node (the actual content of the +metadata node is ignored). Only branches that are marked with +make.implicit metadata are considered as candidates for conversion +into implicit null checks.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case makeImplicit = 14
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + unpredictable + +
      +
      +
      +
      +
      +
      +

      Unpredictable metadata.

      + +

      Unpredictable metadata may be attached to any branch or switch +instruction. It can be used to express the unpredictability of control +flow. Similar to the llvm.expect intrinsic, it may be used to alter +optimizations related to compare and branch instructions. The metadata +is treated as a boolean value; if it exists, it signals that the branch +or switch that it is attached to is completely unpredictable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case unpredictable = 15
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + invariantGroup + +
      +
      +
      +
      +
      +
      +

      Invariant group metadata.

      + +

      The experimental invariant.group metadata may be attached to +load/store instructions referencing a single metadata with no entries. +The existence of invariant.group metadata on the instruction tells the +optimizer that every load and store to the same pointer operand can be +assumed to load or store the same value.

      + +

      Pointers returned by bitcast or getelementptr with only zero indices +are considered the same.

      + +

      Examples:

      +
      @unknownPtr = external global i8
      +...
      +%ptr = alloca i8
      +store i8 42, i8* %ptr, !invariant.group !0
      +call void @foo(i8* %ptr)
      +
      +%a = load i8, i8* %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change
      +call void @foo(i8* %ptr)
      +
      +%newPtr = call i8* @getPointer(i8* %ptr)
      +%c = load i8, i8* %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr
      +
      +%unknownValue = load i8, i8* @unknownPtr
      +store i8 %unknownValue, i8* %ptr, !invariant.group !0 ; Can assume that %unknownValue == 42
      +
      +call void @foo(i8* %ptr)
      +%newPtr2 = call i8* @llvm.launder.invariant.group(i8* %ptr)
      +%d = load i8, i8* %newPtr2, !invariant.group !0  ; Can't step through launder.invariant.group to get value of %ptr
      +
      +...
      +declare void @foo(i8*)
      +declare i8* @getPointer(i8*)
      +declare i8* @llvm.launder.invariant.group(i8*)
      +
      +!0 = !{}
      +
      + +

      The invariant.group metadata must be dropped when replacing one pointer +by another based on aliasing information. This is because +invariant.group is tied to the SSA value of the pointer operand.

      +
      %v = load i8, i8* %x, !invariant.group !0
      +; if %x mustalias %y then we can replace the above instruction with
      +%v = load i8, i8* %y
      +
      + +

      Note that this is an experimental feature, which means that its +semantics might change in the future.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case invariantGroup = 16
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + align + +
      +
      +
      +
      +
      +
      +

      Alignment metadata.

      + +

      This indicates that the pointer value may be assumed by the optimizer to +have the specified alignment. If the pointer value does not have the +specified alignment, behavior is undefined.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case align = 17
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + loop + +
      +
      +
      +
      +
      +
      +

      Loop identifier metadata.

      + +

      It is sometimes useful to attach information to loop constructs. +Currently, loop metadata is implemented as metadata attached to the +branch instruction in the loop latch block. This type of metadata refer +to a metadata node that is guaranteed to be separate for each loop. The +loop identifier metadata is specified with the name llvm.loop.

      + +

      The loop identifier metadata is implemented using a metadata that +refers to itself to avoid merging it with any other identifier +metadata, e.g., during module linkage or function inlining. That is, +each loop should refer to their own identification metadata even if +they reside in separate functions. The following example contains loop +identifier metadata for two separate loop constructs:

      +
      !0 = !{!0}
      +!1 = !{!1}
      +
      + +

      The loop identifier metadata can be used to specify additional per-loop +metadata. Any operands after the first operand can be treated as +user-defined metadata. For example the llvm.loop.unroll.count +suggests an unroll factor to the loop unroller:

      +
      br i1 %exitcond, label %._crit_edge, label %.lr.ph, !llvm.loop !0
      +...
      +!0 = !{!0, !1}
      +!1 = !{!"llvm.loop.unroll.count", i32 4}
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case loop = 18
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + type + +
      +
      +
      +
      +
      +
      +

      Type metadata.

      + +

      Type metadata is a mechanism that allows IR modules to co-operatively +build pointer sets corresponding to addresses within a given set of +globals. LLVM’s control flow integrity implementation uses this metadata +to efficiently check (at each call site) that a given address +corresponds to either a valid vtable or function pointer for a given +class or function type, and its whole-program devirtualization pass uses +the metadata to identify potential callees for a given virtual call.

      + +

      For more information, see Type Metadata.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case type = 19
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + sectionPrefix + +
      +
      +
      +
      +
      +
      +

      Section prefix metadata.

      + +

      LLVM allows an explicit section to be specified for functions. If the +target supports it, it will emit functions to the section specified. +Additionally, the function can be placed in a COMDAT.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case sectionPrefix = 20
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + absoluteSymbol + +
      +
      +
      +
      +
      +
      +

      Absolute symbol metadata.

      + +

      absolute_symbol metadata may be attached to a global variable +declaration. It marks the declaration as a reference to an absolute +symbol, which causes the backend to use absolute relocations for the +symbol even in position independent code, and expresses the possible +ranges that the global variable’s address (not its value) is in, in the +same format as range metadata, with the extension that the pair +all-ones,all-ones may be used to represent the full set.

      + +

      For example (assuming 64-bit pointers):

      +
      @a = external global i8, !absolute_symbol !0 ; Absolute symbol in range [0,256)
      +@b = external global i8, !absolute_symbol !1 ; Absolute symbol in range [0,2^64)
      +...
      +!0 = !{ i64 0, i64 256 }
      +!1 = !{ i64 -1, i64 -1 }
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case absoluteSymbol = 21
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + associated + +
      +
      +
      +
      +
      +
      +

      Associated metadata.

      + +

      associated metadata may be attached to a global object declaration +with a single argument that references another global object.

      + +

      This metadata prevents discarding of the global object in linker GC +unless the referenced object is also discarded. The linker support for +this feature is spotty. For best compatibility, globals carrying this +metadata may also:

      + +
        +
      • Be in a comdat with the referenced global.
      • +
      • Be in @llvm.compiler.used.
      • +
      • Have an explicit section with a name which is a valid C identifier.
      • +
      + +

      It does not have any effect on non-ELF targets.

      + +

      For example:

      +
      $a = comdat any
      +@a = global i32 1, comdat $a
      +@b = internal global i32 2, comdat $a, section "abc", !associated !0
      +!0 = !{i32* @a}
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case associated = 22
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + callees + +
      +
      +
      +
      +
      +
      +

      Callees metadata.

      + +

      Callees metadata may be attached to indirect call sites. If callees +metadata is attached to a call site, and any callee is not among the +set of functions provided by the metadata, the behavior is undefined.

      + +

      The intent of this metadata is to facilitate optimizations such as +indirect-call promotion. For example, in the code below, the call +instruction may only target the add or sub functions:

      +
      %result = call i64 %binop(i64 %x, i64 %y), !callees !0
      +...
      +!0 = !{i64 (i64, i64)* @add, i64 (i64, i64)* @sub}
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case callees = 23
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + irrLoop + +
      +
      +
      +
      +
      +
      +

      Irreducible loop metadata.

      + +

      irr_loop metadata may be attached to the terminator instruction of a +basic block that’s an irreducible loop header (note that an irreducible +loop has more than once header basic blocks.) If irr_loop metadata is +attached to the terminator instruction of a basic block that is not +really an irreducible loop header, the behavior is undefined.

      + +

      The intent of this metadata is to improve the accuracy of the block +frequency propagation. For example, in the code below, the block +header0 may have a loop header weight (relative to the other headers +of the irreducible loop) of 100:

      +
      header0:
      +...
      +br i1 %cmp, label %t1, label %t2, !irr_loop !0
      +...
      +!0 = !{"loop_header_weight", i64 100}
      +
      + +

      Irreducible loop header weights are typically based on profile data.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case irrLoop = 24
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + accessGroup + +
      +
      +
      +
      +
      +
      +

      Memory access group metadata.

      + +

      llvm.access.group metadata can be attached to any instruction that +potentially accesses memory. It can point to a single distinct metadata +node, which we call access group. This node represents all memory access +instructions referring to it via llvm.access.group.

      + +

      When an instruction belongs to multiple access groups, it can also point +to a list of accesses groups, illustrated by the following example:

      +
      %val = load i32, i32* %arrayidx, !llvm.access.group !0
      +...
      +!0 = !{!1, !2}
      +!1 = distinct !{}
      +!2 = distinct !{}
      +
      + +

      It is illegal for the list node to be empty since it might be confused +with an access group.

      + +

      The access group metadata node must be distinct to avoid collapsing +multiple access groups by content. An access group metadata node must +always be empty which can be used to distinguish an access group +metadata node from a list of access groups. Being empty avoids the +situation that the content must be updated which, because metadata is +immutable by design, would required finding and updating all references +to the access group node.

      + +

      The access group can be used to refer to a memory access instruction +without pointing to it directly (which is not possible in global +metadata). Currently, the only metadata making use of it is +llvm.loop.parallel_accesses.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case accessGroup = 25
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + callback + +
      +
      +
      +
      +
      +
      +

      Callback metadata.

      + +

      Callback metadata may be attached to a function declaration, or +definition. The metadata describes how the arguments of a call to a +function are in turn passed to the callback function specified by the +metadata. Thus, the callback metadata provides a partial description of +a call site inside the function with regards to the arguments of a call +to the function. The only semantic restriction on the function itself is +that it is not allowed to inspect or modify arguments referenced in the +callback metadata as pass-through to the callback function.

      + +

      The function is not required to actually invoke the callback function +at runtime. However, the assumptions about not inspecting or modifying +arguments that would be passed to the specified callback function +still hold, even if the callback function is not dynamically invoked. +The function is allowed to invoke the callback function more than once +per invocation. The function is also allowed to invoke (directly or +indirectly) the function passed as a callback through another use. +Finally, the function is also allowed to relay the callback callee +invocation to a different thread.

      + +

      The metadata is structured as follows: At the outer level, callback +metadata is a list of callback encodings. Each encoding starts with a +constant i64 which describes the argument position of the callback +function in the call to the function. The following elements, except +the last, describe what arguments are passed to the callback function. +Each element is again an i64 constant identifying the argument of the +broker that is passed through, or i64 -1 to indicate an unknown or +inspected argument. The order in which they are listed has to be the +same in which they are passed to the callback callee. The last element +of the encoding is a boolean which specifies how variadic arguments of +the broker are handled. If it is true, all variadic arguments of the +broker are passed through to the callback function after the arguments +encoded explicitly before.

      + +

      In the code below, the pthread_create function is marked as such a +function through the !callback !1 metadata. In the example, there is +only one callback encoding, namely !2, associated with it. This +encoding identifies the callback function as the second argument +(i64 2) and the sole argument of the callback function +as the third (i64 3).

      +
      declare !callback !1 dso_local i32 @pthread_create(i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*)
      +...
      +!2 = !{i64 2, i64 3, i1 false}
      +!1 = !{!2}
      +
      + +

      Another example is shown below. The callback callee is the second +argument of the __kmpc_fork_call function (i64 2). The callee is +given two unknown values (each identified by a i64 -1) and afterwards +all variadic arguments that are passed to the __kmpc_fork_call call +(due to the final i1 true).

      +
      declare !callback !0 dso_local void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...)
      +...
      +!1 = !{i64 2, i64 -1, i64 -1, i1 true}
      +!0 = !{!1}
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case callback = 26
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/BinaryFile.html b/docs/Classes/BinaryFile.html new file mode 100644 index 00000000..de5b19ad --- /dev/null +++ b/docs/Classes/BinaryFile.html @@ -0,0 +1,801 @@ + + + + BinaryFile Class Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    BinaryFile

    +
    +
    + +
    public class BinaryFile
    + +
    +
    +

    A BinaryFile is a (mostly) architecture-independent representation of an +in-memory image file.

    + +
    +
    +
    +
      +
    • +
      + + + + buffer + +
      +
      +
      +
      +
      +
      +

      The backing buffer for this binary file.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public let buffer: MemoryBuffer
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + kind + +
      +
      +
      +
      +
      +
      +

      The kind of this binary file.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public let kind: Kind
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + Kind + +
      +
      +
      +
      +
      +
      +

      The kinds of binary files known to LLVM.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public enum Kind
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Creates a Binary File with the contents of a provided memory buffer.

      +
      +

      Throws

      + BinaryFileError if there was an error on creation. + +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(memoryBuffer: MemoryBuffer, in context: Context = .global) throws
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + memoryBuffer + + +
      +

      A memory buffer containing a valid binary file.

      +
      +
      + + context + + +
      +

      The context to allocate the given binary in.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + init(path:) + +
      +
      +
      +
      +
      +
      +

      Creates an ObjectFile with the contents of the object file at +the provided path.

      +
      +

      Throws

      + MemoryBufferError or BinaryFileError if there was an error + on creation + +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public convenience init(path: String) throws
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + path + + +
      +

      The absolute file path on your filesystem.

      +
      +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/BinaryFile/Kind.html b/docs/Classes/BinaryFile/Kind.html new file mode 100644 index 00000000..a40b2fa8 --- /dev/null +++ b/docs/Classes/BinaryFile/Kind.html @@ -0,0 +1,1008 @@ + + + + Kind Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    Kind

    +
    +
    + +
    public enum Kind
    + +
    +
    +

    The kinds of binary files known to LLVM.

    + +
    +
    +
    +
      +
    • +
      + + + + archive + +
      +
      +
      +
      +
      +
      +

      A static library archive file.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case archive
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + machOUniversalBinary + +
      +
      +
      +
      +
      +
      +

      A universal Mach-O binary with multiple component object files for +different architectures.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case machOUniversalBinary
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + coffImportFile + +
      +
      +
      +
      +
      +
      +

      A COFF imports table file.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case coffImportFile
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ir + +
      +
      +
      +
      +
      +
      +

      LLVM IR.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case ir
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + winRes + +
      +
      +
      +
      +
      +
      +

      A Windows resource file.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case winRes
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + coff + +
      +
      +
      +
      +
      +
      +

      A COFF file.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case coff
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + elf32L + +
      +
      +
      +
      +
      +
      +

      A 32-bit little-endian ELF binary.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case elf32L
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + elf32B + +
      +
      +
      +
      +
      +
      +

      A 32-bit big-endian ELF binary.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case elf32B
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + elf64L + +
      +
      +
      +
      +
      +
      +

      A 64-bit little-endian ELF binary.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case elf64L
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + elf64B + +
      +
      +
      +
      +
      +
      +

      A 64-bit big-endian ELF binary.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case elf64B
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + machO32L + +
      +
      +
      +
      +
      +
      +

      A 32-bit little-endian Mach-O binary.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case machO32L
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + machO32B + +
      +
      +
      +
      +
      +
      +

      A 32-bit big-endian Mach-O binary.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case machO32B
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + machO64L + +
      +
      +
      +
      +
      +
      +

      A 64-bit little-endian Mach-O binary.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case machO64L
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + machO64B + +
      +
      +
      +
      +
      +
      +

      A 64-bit big-endian Mach-O binary.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case machO64B
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + wasm + +
      +
      +
      +
      +
      +
      +

      A web assembly binary.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case wasm
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/Comdat.html b/docs/Classes/Comdat.html new file mode 100644 index 00000000..ce6f0d81 --- /dev/null +++ b/docs/Classes/Comdat.html @@ -0,0 +1,704 @@ + + + + Comdat Class Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    Comdat

    +
    +
    + +
    public class Comdat
    + +
    +
    +

    A Comdat object represents a particular COMDAT section in a final +generated ELF or COFF object file. All COMDAT sections are keyed by a +unique name that the linker uses, in conjunction with the section’s +selectionKind to determine how to treat conflicting or identical COMDAT +sections at link time.

    + +

    COMDAT sections are typically used by languages where multiple translation +units may define the same symbol, but where +“One-Definition-Rule” (ODR)-like concepts apply (perhaps because taking the +address of the object referenced by the symbol is defined behavior). For +example, a C++ header file may define an inline function that cannot be +successfully inlined at all call sites. The C++ compiler would then emit +a COMDAT section in each object file for the function with the .any +selection kind and the linker would pick any section it desires before +emitting the final object file.

    + +

    It is important to be aware of the selection kind of a COMDAT section as +these provide strengths and weaknesses at compile-time and link-time. It +is also important to be aware that only certain platforms support mixing +identically-keyed COMDAT sections with mixed selection kinds e.g. COFF +supports mixing .any and .largest, WebAssembly only supports .any, +and Mach-O doesn’t support COMDAT sections at all.

    + +

    When targeting COFF, there are also restrictions on the way global objects +must appear in COMDAT sections. All global objects and aliases to those +global objects must belong to a COMDAT group with the same name and must +have greater than local linkage. Else the local symbol may be renamed in +the event of a collision, defeating code-size savings.

    + +

    The combined use of COMDATS and sections may yield surprising results. +For example:

    +
    let module = Module(name: "COMDATTest")
    +let builder = IRBuilder(module: module)
    +
    +let foo = module.comdat(named: "foo")
    +let bar = module.comdat(named: "bar")
    +
    +var g1 = builder.addGlobal("g1", initializer: IntType.int8.constant(42))
    +g1.comdat = foo
    +var g2 = builder.addGlobal("g2", initializer: IntType.int8.constant(42))
    +g2.comdat = bar
    +
    + +

    From the object file perspective, this requires the creation of two sections +with the same name. This is necessary because both globals belong to +different COMDAT groups and COMDATs, at the object file level, are +represented by sections.

    + +
    +
    +
    +
      +
    • +
      + + + + selectionKind + +
      +
      +
      +
      +
      +
      +

      The selection kind for this COMDAT section.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var selectionKind: Comdat.SelectionKind { get set }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + SelectionKind + +
      +
      +
      +
      +
      +
      +

      A Comdat.SelectionKind describes the behavior of the linker when +linking COMDAT sections.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public enum SelectionKind
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/Comdat/SelectionKind.html b/docs/Classes/Comdat/SelectionKind.html new file mode 100644 index 00000000..a7d9809d --- /dev/null +++ b/docs/Classes/Comdat/SelectionKind.html @@ -0,0 +1,758 @@ + + + + SelectionKind Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    SelectionKind

    +
    +
    + +
    public enum SelectionKind
    + +
    +
    +

    A Comdat.SelectionKind describes the behavior of the linker when +linking COMDAT sections.

    + +
    +
    +
    +
      +
    • +
      + + + + any + +
      +
      +
      +
      +
      +
      +

      The linker may choose any COMDAT section with a matching key.

      + +

      This selection kind is the most relaxed - any section with the same key +but not necessarily identical size or contents can be chosen. Precisely +which section is chosen is implementation-defined.

      + +

      This selection kind is the default for all newly-inserted sections.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case any
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + exactMatch + +
      +
      +
      +
      +
      +
      +

      The linker may choose any identically-keyed COMDAT section and requires +all other referenced data to match its selection’s referenced data.

      + +

      This selection kind requires that the data in each COMDAT section be +identical in length and content. Inclusion of multiple non-identical +COMDAT sections with the same key is an error.

      + +

      For global objects in LLVM, identical contents is defined to mean that +their initializers point to the same global IRValue.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case exactMatch
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + largest + +
      +
      +
      +
      +
      +
      +

      The linker chooses the identically-keyed COMDAT section with the largest +size, ignoring content.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case largest
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + noDuplicates + +
      +
      +
      +
      +
      +
      +

      The COMDAT section with this key is unique.

      + +

      This selection requires that no other COMDAT section have the same key +as this section, making the choice of selection unambiguous. Inclusion +of any other COMDAT section with the same key is an error.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case noDuplicates
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + sameSize + +
      +
      +
      +
      +
      +
      +

      The linker may choose any identically-keyed COMDAT section and requires +all other sections to have the same size as its selection.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case sameSize
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/Context.html b/docs/Classes/Context.html index fcfbe75a..6c6a2b58 100644 --- a/docs/Classes/Context.html +++ b/docs/Classes/Context.html @@ -8,18 +8,26 @@ + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    + +
  • +
    + + + + init() + +
    +
    +
    +
    +
    +
    +

    Creates a new Context object.

    +

    Declaration

    Swift

    -
    public static let global = Context(llvm: LLVMGetGlobalContext()!)
    +
    public init()
    @@ -375,9 +667,9 @@

    Declaration

  • @@ -392,7 +684,67 @@

    Declaration

    Declaration

    Swift

    -
    public init(llvm: LLVMContextRef)
    +
    public init(llvm: LLVMContextRef, ownsContext: Bool = false)
    + +
    +
    +
  • +
    +
  • +
  • +
    + + + + discardValueNames + +
    +
    +
    +
    +
    +
    +

    Returns whether the given context is set to discard all value names.

    + +

    If true, only the names of GlobalValue objects will be available in +the IR. This can be used to save memory and processing time, especially +in release environments.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var discardValueNames: Bool { get set }
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Searches for and retrieves a metadata kind with the given name in this +context. If none is found, one with that name is created and its unique +identifier is returned.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func metadataKind(named name: String, in context: Context = .global) -> UInt32
    @@ -404,8 +756,8 @@

    Declaration

    diff --git a/docs/Classes/DIBuilder.html b/docs/Classes/DIBuilder.html new file mode 100644 index 00000000..fec963df --- /dev/null +++ b/docs/Classes/DIBuilder.html @@ -0,0 +1,5526 @@ + + + + DIBuilder Class Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    DIBuilder

    +
    +
    + +
    public final class DIBuilder
    + +
    +
    +

    A DIBuilder is a helper object used to generate debugging information in +the form of LLVM metadata. A DIBuilder is usually paired with an +IRBuilder to allow for the generation of code and metadata in lock step.

    + +
    +
    +
    +
      +
    • +
      + + + + module + +
      +
      +
      +
      +
      +
      +

      The module this DIBuilder is associated with.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public let module: Module
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Initializes a new DIBuilder object.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(module: Module, allowUnresolved: Bool = true)
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + module + + +
      +

      The parent module.

      +
      +
      + + allowUnresolved + + +
      +

      If true, when this DIBuilder is finalized it will + collect unresolved nodes attached to the module in + order to resolve cycles

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + finalize() + +
      +
      +
      +
      +
      +
      +

      Construct any deferred debug info descriptors.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func finalize()
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Declarations

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Builds a call to a debug intrinsic for declaring a local variable and +inserts it before a given instruction.

      + +

      This intrinsic provides information about a local element +(e.g. a variable) defined in some lexical scope. The variable does not +have to be physically represented in the source.

      + +

      Each variable may have at most one corresponding llvm.dbg.declare. A +variable declaration is not control-dependent: A variable is declared at +most once, and that declaration remains in effect until the lifetime of +that variable ends.

      + +

      lldb.dbg.declare can make optimizing code that needs accurate debug info +difficult because of these scoping constraints.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildDeclare(
      +  of variable: IRValue,
      +  before: IRInstruction,
      +  metadata: LocalVariableMetadata,
      +  expr: ExpressionMetadata,
      +  location: DebugLocation
      +)
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + +
      + + variable + + +
      +

      The IRValue of a variable to declare.

      +
      +
      + + before + + +
      +

      The instruction before which the intrinsic will be inserted.

      +
      +
      + + metadata + + +
      +

      Local variable metadata.

      +
      +
      + + expr + + +
      +

      A “complex expression” that modifies the current + variable declaration.

      +
      +
      + + location + + +
      +

      The location of the variable in source.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Builds a call to a debug intrinsic for declaring a local variable and +inserts it at the end of a given basic block.

      + +

      This intrinsic provides information about a local element +(e.g. a variable) defined in some lexical scope. The variable does not +have to be physically represented in the source.

      + +

      Each variable may have at most one corresponding llvm.dbg.declare. A +variable declaration is not control-dependent: A variable is declared at +most once, and that declaration remains in effect until the lifetime of +that variable ends.

      + +

      lldb.dbg.declare can make optimizing code that needs accurate debug info +difficult because of these scoping constraints.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildDeclare(
      +  of variable: IRValue,
      +  atEndOf block: BasicBlock,
      +  metadata: LocalVariableMetadata,
      +  expr: ExpressionMetadata,
      +  location: DebugLocation
      +)
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + +
      + + variable + + +
      +

      The IRValue of a variable to declare.

      +
      +
      + + block + + +
      +

      The block in which the intrinsic will be placed.

      +
      +
      + + metadata + + +
      +

      Local variable metadata.

      +
      +
      + + expr + + +
      +

      A “complex expression” that modifies the current + variable declaration.

      +
      +
      + + location + + +
      +

      The location of the variable in source.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Builds a call to a debug intrinsic for providing information about the +value of a local variable and inserts it before a given instruction.

      + +

      This intrinsic provides information to model the result of a source +variable being set to a new value.

      + +

      This intrinsic is built to describe the value of a source variable +directly. That is, the source variable may be a value or an address, +but the value for that variable provided to this intrinsic is considered +without interpretation to be the value of the given variable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildDbgValue(
      +  of value: IRValue,
      +  to metadata: LocalVariableMetadata,
      +  before: IRInstruction,
      +  expr: ExpressionMetadata,
      +  location: DebugLocation
      +)
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + +
      + + value + + +
      +

      The value to set the given variable to.

      +
      +
      + + metadata + + +
      +

      Metadata for the given local variable.

      +
      +
      + + before + + +
      +

      The instruction before which the intrinsic will be inserted.

      +
      +
      + + expr + + +
      +

      A “complex expression” that modifies the given value.

      +
      +
      + + location + + +
      +

      The location of the variable assignment in source.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Builds a call to a debug intrinsic for providing information about the +value of a local variable and inserts it before a given instruction.

      + +

      This intrinsic provides information to model the result of a source +variable being set to a new value.

      + +

      This intrinsic is built to describe the value of a source variable +directly. That is, the source variable may be a value or an address, +but the value for that variable provided to this intrinsic is considered +without interpretation to be the value of the given variable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildDbgValue(
      +  of value: IRValue,
      +  to metadata: LocalVariableMetadata,
      +  atEndOf block: BasicBlock,
      +  expr: ExpressionMetadata,
      +  location: DebugLocation
      +)
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + +
      + + value + + +
      +

      The value to set the given variable to.

      +
      +
      + + metadata + + +
      +

      Metadata for the given local variable.

      +
      +
      + + block + + +
      +

      The block in which the intrinsic will be placed.

      +
      +
      + + expr + + +
      +

      A “complex expression” that modifies the given value.

      +
      +
      + + location + + +
      +

      The location of the variable assignment in source.

      +
      +
      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Scope Entities

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      A CompileUnit provides an anchor for all debugging information generated +during this instance of compilation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildCompileUnit(
      +  for language: DWARFSourceLanguage,
      +  in file: FileMetadata,
      +  kind: DWARFEmissionKind,
      +  optimized: Bool = false,
      +  splitDebugInlining: Bool = false,
      +  debugInfoForProfiling: Bool = false,
      +  flags: [String] = [],
      +  runtimeVersion: Int = 0,
      +  splitDWARFPath: String = "",
      +  identity: String = "",
      +  sysRoot: String = "",
      +  sdkRoot: String = ""
      +) -> CompileUnitMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + language + + +
      +

      The source programming language.

      +
      +
      + + file + + +
      +

      The file descriptor for the source file.

      +
      +
      + + kind + + +
      +

      The kind of debug info to generate.

      +
      +
      + + optimized + + +
      +

      A flag that indicates whether optimization is enabled or +not when compiling the source file. Defaults to false.

      +
      +
      + + splitDebugInlining + + +
      +

      If true, minimal debug info in the module is +emitted to facilitate online symbolication and stack traces in the +absence of .dwo/.dwp files when using Split DWARF.

      +
      +
      + + debugInfoForProfiling + + +
      +

      A flag that indicates whether to emit extra +debug information for profile collection.

      +
      +
      + + flags + + +
      +

      Command line options that are embedded in debug info for use +by third-party tools.

      +
      +
      + + splitDWARFPath + + +
      +

      The path to the split DWARF file.

      +
      +
      + + identity + + +
      +

      The identity of the tool that is compiling this source file.

      +
      +
      + + sysRoot + + +
      +

      The Clang system root (the value of the -isysroot that’s passed to clang).

      +
      +
      + + sdkRoot + + +
      +

      The SDK root – on Darwin platforms, this is the last component of the sysroot.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing a compilation-unit level scope.

      +
      +
      +
      +
    • +
    • +
      + + + + buildFile(named:in:) + +
      +
      +
      +
      +
      +
      +

      Create a file descriptor to hold debugging information for a file.

      + +

      Global variables and top level functions would be defined using this +context. File descriptors also provide context for source line +correspondence.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildFile(
      +  named name: String, in directory: String
      +) -> FileMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + name + + +
      +

      The name of the file.

      +
      +
      + + directory + + +
      +

      The directory the file resides in.

      +
      +
      +
      +
      +

      Return Value

      +

      A value represending metadata about a given file.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Creates a new descriptor for a module with the specified parent scope.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildModule(
      +  named name: String,
      +  scope: DIScope,
      +  macros: [String] = [],
      +  includePath: String = "",
      +  includeSystemRoot: String = ""
      +) -> ModuleMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Module name.

      +
      +
      + + scope + + +
      +

      The parent scope containing this module declaration.

      +
      +
      + + macros + + +
      +

      A list of -D macro definitions as they would appear on a + command line.

      +
      +
      + + includePath + + +
      +

      The path to the module map file.

      +
      +
      + + includeSystemRoot + + +
      +

      The Clang system root (value of -isysroot).

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Creates a new descriptor for a namespace with the specified parent scope.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildNameSpace(
      +  named name: String, scope: DIScope, exportsSymbols: Bool
      +) -> NameSpaceMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + name + + +
      +

      NameSpace name.

      +
      +
      + + scope + + +
      +

      The parent scope containing this module declaration.

      +
      +
      + + exportsSymbols + + +
      +

      Whether or not the namespace exports symbols, e.g. + this is true of C++ inline namespaces.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a new descriptor for the specified subprogram.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildFunction(
      +  named name: String, linkageName: String,
      +  scope: DIScope, file: FileMetadata, line: Int, scopeLine: Int,
      +  type: DISubroutineType,
      +  flags: DIFlags,
      +  isLocal: Bool = true, isDefinition: Bool = true,
      +  isOptimized: Bool = false
      +) -> FunctionMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Function name.

      +
      +
      + + linkageName + + +
      +

      Mangled function name.

      +
      +
      + + scope + + +
      +

      Function scope.

      +
      +
      + + file + + +
      +

      File where this variable is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + scopeLine + + +
      +

      Set to the beginning of the scope this starts

      +
      +
      + + type + + +
      +

      Function type.

      +
      +
      + + flags + + +
      +

      Flags to emit DWARF attributes.

      +
      +
      + + isLocal + + +
      +

      True if this function is not externally visible.

      +
      +
      + + isDefinition + + +
      +

      True if this is a function definition.

      +
      +
      + + isOptimized + + +
      +

      True if optimization is enabled.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a descriptor for a lexical block with the specified parent context.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildLexicalBlock(
      +  scope: DIScope, file: FileMetadata, line: Int, column: Int
      +) -> LexicalBlockMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + +
      + + scope + + +
      +

      Parent lexical block.

      +
      +
      + + File + + +
      +

      Source file.

      +
      +
      + + line + + +
      +

      The line in the source file.

      +
      +
      + + column + + +
      +

      The column in the source file.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a descriptor for a lexical block with a new file attached.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildLexicalBlockFile(
      +  scope: DIScope, file: FileMetadata, discriminator: Int
      +) -> LexicalBlockFileMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + scope + + +
      +

      Lexical block.

      +
      +
      + + file + + +
      +

      Source file.

      +
      +
      + + discriminator + + +
      +

      DWARF path discriminator value.

      +
      +
      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Local Variables

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Create a new descriptor for a local auto variable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildLocalVariable(
      +  named name: String,
      +  scope: DIScope, file: FileMetadata, line: Int,
      +  type: DIType, alwaysPreserve: Bool = false,
      +  flags: DIFlags = [], alignment: Alignment
      +) -> LocalVariableMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Variable name.

      +
      +
      + + scope + + +
      +

      The local scope the variable is declared in.

      +
      +
      + + file + + +
      +

      File where this variable is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + type + + +
      +

      Metadata describing the type of the variable.

      +
      +
      + + alwaysPreserve + + +
      +

      If true, this descriptor will survive optimizations.

      +
      +
      + + flags + + +
      +

      Flags.

      +
      +
      + + alignment + + +
      +

      Variable alignment.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a new descriptor for a function parameter variable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildParameterVariable(
      +  named name: String, index: Int,
      +  scope: DIScope, file: FileMetadata, line: Int,
      +  type: DIType, alwaysPreserve: Bool = false,
      +  flags: DIFlags = []
      +) -> LocalVariableMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Variable name.

      +
      +
      + + index + + +
      +

      Unique argument number for this variable; starts at 1.

      +
      +
      + + scope + + +
      +

      The local scope the variable is declared in.

      +
      +
      + + file + + +
      +

      File where this variable is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + type + + +
      +

      Metadata describing the type of the variable.

      +
      +
      + + alwaysPreserve + + +
      +

      If true, this descriptor will survive optimizations.

      +
      +
      + + flags + + +
      +

      Flags.

      +
      +
      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Debug Locations

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Creates a new debug location that describes a source location.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildDebugLocation(
      +  at location : (line: Int, column: Int),
      +  in scope: DIScope,
      +  inlinedAt: DIScope? = nil
      +) -> DebugLocation
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + location + + +
      +

      The location of the line and column for this information. + If the location of the value is unknown, pass + (line: 0, column: 0).

      +
      +
      + + scope + + +
      +

      The scope this debug location resides in.

      +
      +
      + + inlinedAt + + +
      +

      If this location has been inlined somewhere, the scope in + which it was inlined. Defaults to nil.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing a debug location.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create subroutine type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildSubroutineType(
      +  in file: FileMetadata,
      +  parameterTypes: [DIType], returnType: DIType? = nil,
      +  flags: DIFlags = []
      +) -> DISubroutineType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + +
      + + file + + +
      +

      The file in which the subroutine resides.

      +
      +
      + + parameterTypes + + +
      +

      An array of subroutine parameter types.

      +
      +
      + + returnType + + +
      +

      The return type of the function, if any.

      +
      +
      + + flags + + +
      +

      Flags to emit DWARF attributes.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for an enumeration.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildEnumerationType(
      +  named name: String,
      +  scope: DIScope, file: FileMetadata, line: Int,
      +  size: Size, alignment: Alignment,
      +  elements: [DIType], underlyingType: DIType
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Enumeration name.

      +
      +
      + + scope + + +
      +

      Scope in which this enumeration is defined.

      +
      +
      + + file + + +
      +

      File where this member is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + size + + +
      +

      Member size.

      +
      +
      + + alignment + + +
      +

      Member alignment.

      +
      +
      + + elements + + +
      +

      Enumeration elements.

      +
      +
      + + numElements + + +
      +

      Number of enumeration elements.

      +
      +
      + + underlyingType + + +
      +

      Underlying type of a C++11/ObjC fixed enum.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a union.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildUnionType(
      +  named name: String,
      +  scope: DIScope, file: FileMetadata, line: Int,
      +  size: Size, alignment: Alignment, flags: DIFlags,
      +  elements: [DIType],
      +  runtimeVersion: Int = 0, uniqueID: String = ""
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Union name.

      +
      +
      + + scope + + +
      +

      Scope in which this union is defined.

      +
      +
      + + file + + +
      +

      File where this member is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + size + + +
      +

      Member size.

      +
      +
      + + alignment + + +
      +

      Member alignment.

      +
      +
      + + flags + + +
      +

      Flags to encode member attribute, e.g. private

      +
      +
      + + elements + + +
      +

      Union elements.

      +
      +
      + + runtimeVersion + + +
      +

      Optional parameter, Objective-C runtime version.

      +
      +
      + + uniqueID + + +
      +

      A unique identifier for the union.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for an array.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildArrayType(
      +  of elementType: DIType,
      +  size: Size, alignment: Alignment,
      +  subscripts: [Range<Int>] = []
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + +
      + + elementType + + +
      +

      Metadata describing the type of the elements.

      +
      +
      + + size + + +
      +

      The total size of the array.

      +
      +
      + + alignment + + +
      +

      The alignment of the array.

      +
      +
      + + subscripts + + +
      +

      A list of ranges of valid subscripts into the array. For + unbounded arrays, pass the unchecked range -1...0.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a vector.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildVectorType(
      +  of elementType: DIType,
      +  size: Size, alignment: Alignment,
      +  subscripts: [Range<Int>] = []
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + +
      + + elementType + + +
      +

      Metadata describing the type of the elements.

      +
      +
      + + size + + +
      +

      The total size of the array.

      +
      +
      + + alignment + + +
      +

      The alignment of the array.

      +
      +
      + + subscripts + + +
      +

      A list of ranges of valid subscripts into the array. For + unbounded arrays, pass the unchecked range -1...0.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a DWARF unspecified type.

      + +

      Some languages have constructs in which a type may be left unspecified or +the absence of a type may be explicitly indicated. For example, C++ +permits using the auto return type specifier for the return type of a +member function declaration. The actual return type is deduced based on +the definition of the function, so it may not be known when the function +is declared. The language implementation can provide an unspecified type +entry with the name auto which can be referenced by the return type +attribute of a function declaration entry. When the function is later +defined, the subprogram entry for the definition includes a reference to +the actual return type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildUnspecifiedType(named name: String) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + name + + +
      +

      The name of the type

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a basic type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildBasicType(
      +  named name: String, encoding: DIAttributeTypeEncoding, flags: DIFlags, size: Size
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Type name.

      +
      +
      + + encoding + + +
      +

      The basic type encoding

      +
      +
      + + size + + +
      +

      Size of the type.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a pointer.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildPointerType(
      +  pointee: DIType, size: Size, alignment: Alignment,
      +  addressSpace: AddressSpace = .zero, name: String = ""
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + +
      + + pointee + + +
      +

      Type pointed by this pointer.

      +
      +
      + + size + + +
      +

      The size of the pointer value.

      +
      +
      + + alignment + + +
      +

      The alignment of the pointer.

      +
      +
      + + addressSpace + + +
      +

      The address space the pointer type reside in.

      +
      +
      + + name + + +
      +

      The name of the pointer type.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a struct.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildStructType(
      +  named name: String,
      +  scope: DIScope, file: FileMetadata, line: Int,
      +  size: Size, alignment: Alignment, flags: DIFlags = [],
      +  baseType: DIType? = nil, elements: [DIType] = [],
      +  vtableHolder: DIType? = nil, runtimeVersion: Int = 0, uniqueID: String = ""
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Struct name.

      +
      +
      + + scope + + +
      +

      Scope in which this struct is defined.

      +
      +
      + + file + + +
      +

      File where this member is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + size + + +
      +

      The total size of the struct and its members.

      +
      +
      + + alignment + + +
      +

      The alignment of the struct.

      +
      +
      + + flags + + +
      +

      Flags to encode member attributes.

      +
      +
      + + elements + + +
      +

      Struct elements.

      +
      +
      + + vtableHolder + + +
      +

      The object containing the vtable for the struct.

      +
      +
      + + runtimeVersion + + +
      +

      Optional parameter, Objective-C runtime version.

      +
      +
      + + uniqueId + + +
      +

      A unique identifier for the struct.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a member.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildMemberType(
      +  of parentType: DIType, scope: DIScope, name: String,
      +  file: FileMetadata, line: Int,
      +  size: Size, alignment: Alignment, offset: Size, flags: DIFlags = []
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + parentType + + +
      +

      Parent type.

      +
      +
      + + scope + + +
      +

      Member scope.

      +
      +
      + + name + + +
      +

      Member name.

      +
      +
      + + file + + +
      +

      File where this member is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + size + + +
      +

      Member size.

      +
      +
      + + alignment + + +
      +

      Member alignment.

      +
      +
      + + offset + + +
      +

      Member offset.

      +
      +
      + + flags + + +
      +

      Flags to encode member attributes.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a C++ static data member.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildStaticMemberType(
      +  of parentType: DIType, scope: DIScope, name: String, file: FileMetadata,
      +  line: Int, alignment: Alignment, flags: DIFlags = [],
      +  initialValue: IRConstant? = nil
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + parentType + + +
      +

      Type of the static member.

      +
      +
      + + scope + + +
      +

      Member scope.

      +
      +
      + + name + + +
      +

      Member name.

      +
      +
      + + file + + +
      +

      File where this member is declared.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + alignment + + +
      +

      Member alignment.

      +
      +
      + + flags + + +
      +

      Flags to encode member attributes.

      +
      +
      + + initialValue + + +
      +

      Constant initializer of the member.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a pointer to member.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildMemberPointerType(
      +  pointee: DIType, baseType: DIType,
      +  size: Size, alignment: Alignment,
      +  flags: DIFlags = []
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + +
      + + pointee + + +
      +

      Type pointed to by this pointer.

      +
      +
      + + baseType + + +
      +

      Type for which this pointer points to members of.

      +
      +
      + + size + + +
      +

      Size.

      +
      +
      + + alignment + + +
      +

      Alignment.

      +
      +
      + + flags + + +
      +

      Flags.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a uniqued DIType* clone with FlagObjectPointer and +FlagArtificial set.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildObjectPointerType(pointee: DIType) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + pointee + + +
      +

      The underlying type to which this pointer points.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a qualified type, e.g. ‘const int’.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildQualifiedType(_ tag: DWARFTag, _ type: DIType) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + tag + + +
      +

      Tag identifying type.

      +
      +
      + + type + + +
      +

      Base Type.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a c++ style reference or rvalue +reference type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildReferenceType(_ tag: DWARFTag, _ type: DIType) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + tag + + +
      +

      Tag identifying type.

      +
      +
      + + type + + +
      +

      Base Type.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + buildNullPtrType() + +
      +
      +
      +
      +
      +
      +

      Create C++11 nullptr type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildNullPtrType() -> DIType
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a typedef.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildTypedef(
      +  of type: DIType,
      +  name: String,
      +  alignment: Alignment,
      +  scope: DIScope,
      +  file: FileMetadata,
      +  line: Int
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + type + + +
      +

      Original type.

      +
      +
      + + name + + +
      +

      Typedef name.

      +
      +
      + + alignment + + +
      +

      Alignment of the type.

      +
      +
      + + scope + + +
      +

      The surrounding context for the typedef.

      +
      +
      + + file + + +
      +

      File where this type is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry to establish inheritance relationship +between two types.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildInheritance(
      +  of derived: DIType, to base: DIType,
      +  baseOffset: Size, virtualBasePointerOffset: Size, flags: DIFlags = []
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + +
      + + derived + + +
      +

      Original type.

      +
      +
      + + base + + +
      +

      Base type. Ty is inherits from base.

      +
      +
      + + baseOffset + + +
      +

      Base offset.

      +
      +
      + + virtualBasePointerOffset + + +
      +

      Virtual base pointer offset.

      +
      +
      + + flags + + +
      +

      Flags to describe inheritance attribute, e.g. private

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a permanent forward-declared type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildForwardDeclaration(
      +  named name: String, tag: DWARFTag,
      +  scope: DIScope, file: FileMetadata, line: Int,
      +  size: Size, alignment: Alignment,
      +  runtimeLanguage: Int = 0, uniqueID: String = ""
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Type name.

      +
      +
      + + tag + + +
      +

      A unique tag for this type.

      +
      +
      + + scope + + +
      +

      Type scope.

      +
      +
      + + file + + +
      +

      File where this type is defined.

      +
      +
      + + line + + +
      +

      Line number where this type is defined.

      +
      +
      + + size + + +
      +

      Member size.

      +
      +
      + + alignment + + +
      +

      Member alignment.

      +
      +
      + + runtimeLanguage + + +
      +

      Indicates runtime version for languages like +Objective-C.

      +
      +
      + + uniqueID + + +
      +

      A unique identifier for the type.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a temporary forward-declared type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildReplaceableCompositeType(
      +  named name: String, tag: DWARFTag,
      +  scope: DIScope, file: FileMetadata, line: Int,
      +  size: Size, alignment: Alignment, flags: DIFlags = [],
      +  runtimeVersion: Int = 0, uniqueID: String = ""
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Type name.

      +
      +
      + + tag + + +
      +

      A unique tag for this type.

      +
      +
      + + scope + + +
      +

      Type scope.

      +
      +
      + + file + + +
      +

      File where this type is defined.

      +
      +
      + + line + + +
      +

      Line number where this type is defined. +Objective-C.

      +
      +
      + + size + + +
      +

      Member size.

      +
      +
      + + alignment + + +
      +

      Member alignment.

      +
      +
      + + flags + + +
      +

      Flags.

      +
      +
      + + runtimeVersion + + +
      +

      Indicates runtime version for languages like

      +
      +
      + + uniqueID + + +
      +

      A unique identifier for the type.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a bit field member.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildBitFieldMemberType(
      +  named name: String, type: DIType,
      +  scope: DIScope, file: FileMetadata, line: Int,
      +  size: Size, offset: Size, storageOffset: Size,
      +  flags: DIFlags = []
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Member name.

      +
      +
      + + type + + +
      +

      Parent type.

      +
      +
      + + scope + + +
      +

      Member scope.

      +
      +
      + + file + + +
      +

      File where this member is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + size + + +
      +

      Member size.

      +
      +
      + + offset + + +
      +

      Member offset.

      +
      +
      + + storageOffset + + +
      +

      Member storage offset.

      +
      +
      + + flags + + +
      +

      Flags to encode member attribute.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for a class.

      + +
        +
      • name: Class name.
      • +
      • baseType: Debug info of the base class of this type.
      • +
      • scope: Scope in which this class is defined.
      • +
      • file: File where this member is defined.
      • +
      • line: Line number.
      • +
      • size: Member size.
      • +
      • alignment: Member alignment.
      • +
      • offset: Member offset.
      • +
      • flags: Flags to encode member attribute, e.g. private.
      • +
      • elements: Class members.
      • +
      • vtableHolder: Debug info of the base class that contains vtable +for this type. This is used in DW_AT_containing_type.
      • +
      • uniqueID: A unique identifier for the type.
      • +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildClassType(
      +  named name: String, derivedFrom baseType: DIType?,
      +  scope: DIScope, file: FileMetadata, line: Int,
      +  size: Size, alignment: Alignment, offset: Size, flags: DIFlags,
      +  elements: [DIType] = [],
      +  vtableHolder: DIType? = nil, uniqueID: String = ""
      +) -> DIType
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a uniqued DIType* clone with FlagArtificial set.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildArtificialType(_ type: DIType) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The underlying type.

      +
      +
      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Imported Entities

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Create a descriptor for an imported module.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildImportedModule(
      +  in context: DIScope, namespace: NameSpaceMetadata,
      +  file: FileMetadata, line: Int
      +) -> ImportedEntityMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + +
      + + context + + +
      +

      The scope this module is imported into

      +
      +
      + + namespace + + +
      +

      The namespace being imported here.

      +
      +
      + + file + + +
      +

      File where the declaration is located.

      +
      +
      + + line + + +
      +

      Line number of the declaration.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a descriptor for an imported module.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildImportedModule(
      +  in context: DIScope, aliasee: ImportedEntityMetadata,
      +  file: FileMetadata, line: Int
      +) -> ImportedEntityMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + +
      + + context + + +
      +

      The scope this module is imported into.

      +
      +
      + + aliasee + + +
      +

      An aliased namespace.

      +
      +
      + + file + + +
      +

      File where the declaration is located.

      +
      +
      + + line + + +
      +

      Line number of the declaration.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a descriptor for an imported module.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildImportedModule(
      +  in context: DIScope, module: ModuleMetadata, file: FileMetadata, line: Int
      +) -> ImportedEntityMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + +
      + + context + + +
      +

      The scope this module is imported into.

      +
      +
      + + module + + +
      +

      The module being imported here

      +
      +
      + + file + + +
      +

      File where the declaration is located.

      +
      +
      + + line + + +
      +

      Line number of the declaration.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a descriptor for an imported function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildImportedDeclaration(
      +  in context: DIScope, declaration: IRMetadata,
      +  file: FileMetadata, line: Int, name: String = ""
      +) -> ImportedEntityMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + +
      + + context + + +
      +

      The scope this module is imported into.

      +
      +
      + + declaration + + +
      +

      The declaration (or definition) of a function, type, or + variable.

      +
      +
      + + file + + +
      +

      File where the declaration is located.

      +
      +
      + + line + + +
      +

      Line number of the declaration.

      +
      +
      + + name + + +
      +

      The name of the imported declaration.

      +
      +
      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Objective-C

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for Objective-C instance variable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildObjCIVar(
      +  for property: ObjectiveCPropertyMetadata, name: String, type: DIType,
      +  file: FileMetadata, line: Int,
      +  size: Size, alignment: Alignment, offset: Size, flags: DIFlags = []
      +) -> DIType
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + property + + +
      +

      The property associated with this ivar.

      +
      +
      + + name + + +
      +

      Member name.

      +
      +
      + + type + + +
      +

      Type.

      +
      +
      + + file + + +
      +

      File where this member is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + size + + +
      +

      Member size.

      +
      +
      + + alignment + + +
      +

      Member alignment.

      +
      +
      + + offset + + +
      +

      Member offset.

      +
      +
      + + flags + + +
      +

      Flags to encode member attributes.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a debugging information entry for Objective-C property.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildObjCProperty(
      +  named name: String, type: DIType,
      +  file: FileMetadata, line: Int,
      +  getter: String, setter: String,
      +  propertyAttributes: ObjectiveCPropertyAttribute
      +) -> ObjectiveCPropertyMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Property name.

      +
      +
      + + type + + +
      +

      Type.

      +
      +
      + + file + + +
      +

      File where this property is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + getter + + +
      +

      Name of the Objective C property getter selector.

      +
      +
      + + setter + + +
      +

      Name of the Objective C property setter selector.

      +
      +
      + + propertyAttributes + + +
      +

      Objective C property attributes.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + buildExpression(_:) + +
      +
      +
      +
      +
      +
      +

      Create a new descriptor for the specified variable which has a complex +address expression for its address.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildExpression(_ expression: [DWARFExpression]) -> ExpressionMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + expression + + +
      +

      An array of complex address operations.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a new descriptor for the specified variable that does not have an +address, but does have a constant value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildConstantExpresion(_ value: Int) -> ExpressionMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + value + + +
      +

      The constant value.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Create a new descriptor for the specified variable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildGlobalExpression(
      +  named name: String, linkageName: String, type: DIType,
      +  scope: DIScope, file: FileMetadata, line: Int,
      +  isLocal: Bool = true,
      +  expression: ExpressionMetadata? = nil,
      +  declaration: IRMetadata? = nil,
      +  alignment: Alignment
      +) -> ExpressionMetadata
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + name + + +
      +

      Name of the variable.

      +
      +
      + + linkageName + + +
      +

      Mangled name of the variable.

      +
      +
      + + type + + +
      +

      Variable Type.

      +
      +
      + + scope + + +
      +

      Variable scope.

      +
      +
      + + file + + +
      +

      File where this variable is defined.

      +
      +
      + + line + + +
      +

      Line number.

      +
      +
      + + isLocal + + +
      +

      Boolean flag indicate whether this variable is +externally visible or not.

      +
      +
      + + expression + + +
      +

      The location of the global relative to the attached +GlobalVariable.

      +
      +
      + + declaration + + +
      +

      Reference to the corresponding declaration.

      +
      +
      + + alignment + + +
      +

      Variable alignment

      +
      +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/Function.html b/docs/Classes/Function.html index 434a4612..bd73e24f 100644 --- a/docs/Classes/Function.html +++ b/docs/Classes/Function.html @@ -8,18 +8,26 @@ + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
  • +
  • +
    + + + + basicBlockCount + +
    +
    +
    +
    +
    +
    +

    Retrieves the number of basic blocks in this function

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var basicBlockCount: Int { get }
    @@ -497,9 +860,9 @@

    Declaration

  • @@ -508,8 +871,11 @@

    Declaration

    Computes the address of the specified basic block in this function.

    +
    +

    Warning

    + Taking the address of the entry block is illegal. -

    Taking the address of the entry block is illegal.

    +

    This value only has defined behavior when used as an operand to the indirectbr instruction, or for comparisons against null. Pointer @@ -528,7 +894,7 @@

    Declaration

    Declaration

    Swift

    -
    public func address(of block: BasicBlock) -> BasicBlock.Address?
    +
    public func address(of block: BasicBlock) -> BasicBlock.Address?
    @@ -563,9 +929,9 @@

    Return Value

  • @@ -580,7 +946,7 @@

    Return Value

    Declaration

    Swift

    -
    public func previous() -> Function?
    +
    public func previous() -> Function?
    @@ -590,9 +956,9 @@

    Declaration

  • - + - next() + next()
    @@ -607,7 +973,7 @@

    Declaration

    Declaration

    Swift

    -
    public func next() -> Function?
    +
    public func next() -> Function?
    @@ -617,9 +983,9 @@

    Declaration

  • @@ -634,7 +1000,7 @@

    Declaration

    Declaration

    Swift

    -
    public func parameter(at index: Int) -> Parameter?
    +
    public func parameter(at index: Int) -> Parameter?
    @@ -667,9 +1033,9 @@

    Return Value

  • @@ -684,7 +1050,7 @@

    Return Value

    Declaration

    Swift

    -
    public var firstParameter: Parameter?
    +
    public var firstParameter: Parameter? { get }
    @@ -694,9 +1060,9 @@

    Declaration

  • @@ -711,7 +1077,7 @@

    Declaration

    Declaration

    Swift

    -
    public var lastParameter: Parameter?
    +
    public var lastParameter: Parameter? { get }
    @@ -721,9 +1087,9 @@

    Declaration

  • @@ -738,7 +1104,34 @@

    Declaration

    Declaration

    Swift

    -
    public var parameters: [IRValue]
    +
    public var parameters: [IRValue] { get }
    + +
    +
    +
  • +
    +
  • +
  • +
    + + + + parameterCount + +
    +
    +
    +
    +
    +
    +

    Retrieves the number of parameter values in this function.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var parameterCount: Int { get }
    @@ -748,9 +1141,9 @@

    Declaration

  • @@ -765,7 +1158,7 @@

    Declaration

    Declaration

    Swift

    -
    public func appendBasicBlock(named name: String, in context: Context? = nil) -> BasicBlock
    +
    public func appendBasicBlock(named name: String, in context: Context? = nil) -> BasicBlock
    @@ -808,9 +1201,9 @@

    Parameters

  • - - - delete() + + + append(_:)
    @@ -818,21 +1211,67 @@

    Parameters

    -

    Deletes the function from its containing module.

    -
    -

    Note

    - This does not remove calls to this function from the - module. Ensure you have removed all instructions that reference - this function before deleting it. +

    Appends the named basic block to the body of this function.

    -
    +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func append(_ basicBlock: BasicBlock)
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + basicBlock + + +
    +

    The block to append.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + delete() + +
    +
    +
    +
    +
    +
    +

    Deletes the function from its containing module.

    +
    +

    Note

    + This does not remove calls to this function from the + module. Ensure you have removed all instructions that reference + this function before deleting it. + +

    Declaration

    Swift

    -
    public func delete()
    +
    public func delete()
    @@ -842,9 +1281,9 @@

    Declaration

  • - + - asLLVM() + asLLVM()
    @@ -859,7 +1298,360 @@

    Declaration

    Declaration

    Swift

    -
    public func asLLVM() -> LLVMValueRef
    +
    public func asLLVM() -> LLVMValueRef
    + +
    +
    +
  • +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Adds an enum attribute to the function, its return value or one of its +parameters.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func addAttribute(_ attrKind: AttributeKind, value: UInt64 = 0, to index: AttributeIndex) -> EnumAttribute
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + attrKind + + +
    +

    The kind of the attribute to add.

    +
    +
    + + value + + +
    +

    The optional value of the attribute.

    +
    +
    + + index + + +
    +

    The index representing the function, its return value +or one of its parameters.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Adds a string attribute to the function, its return value or one of its +parameters.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    @discardableResult
    +public func addAttribute(_ name: String, value: String = "", to index: AttributeIndex) -> StringAttribute
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + name + + +
    +

    The name of the attribute to add.

    +
    +
    + + value + + +
    +

    The optional value of the attribute.

    +
    +
    + + index + + +
    +

    The index representing the function, its return value +or one of its parameters.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Removes an attribute from the function, its return value or one of its +parameters.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func removeAttribute(_ attr: Attribute, from index: AttributeIndex)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + attr + + +
    +

    The attribute to remove.

    +
    +
    + + index + + +
    +

    The index representing the function, its return value +or one of its parameters.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Removes an enum attribute from the function, its return value or one of +its parameters.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func removeAttribute(_ attrKind: AttributeKind, from index: AttributeIndex)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + attr + + +
    +

    The kind of the attribute to remove.

    +
    +
    + + index + + +
    +

    The index representing the function, its return value +or one of its parameters.

    +
    +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Removes a string attribute from the function, its return value or one of +its parameters.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func removeAttribute(_ name: String, from index: AttributeIndex)
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + name + + +
    +

    The name of the attribute to remove.

    +
    +
    + + index + + +
    +

    The index representing the function, its return value +or one of its parameters.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + attributes(at:) + +
    +
    +
    +
    +
    +
    +

    Gets the attributes of the function, its return value or its parameters.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func attributes(at index: AttributeIndex) -> [Attribute]
    @@ -871,8 +1663,8 @@

    Declaration

  • diff --git a/docs/Classes/FunctionPassManager.html b/docs/Classes/FunctionPassManager.html index 46b7a901..87b8b3e6 100644 --- a/docs/Classes/FunctionPassManager.html +++ b/docs/Classes/FunctionPassManager.html @@ -8,18 +8,26 @@ + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
  • - - -
    - -
    +
    +
    + + +
    + +

    Debug Information

    +

    +
    +
    +
      +
    • +
      + + + + currentDebugLocation + +
      +
      +
      +
      +
      +
      +

      Access location information used by debugging information.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var currentDebugLocation: DebugLocation? { get set }
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Set the floating point math metadata to be used for floating-point +operations.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var defaultFloatingPointMathTag: MDNode? { get set }
      + +
      +
      +
      +
      +
    • +
    +
    - -

    Convenience Instructions

    -
    +
    + +

    Convenience Instructions

    +

    +
    - - -
    - -
    • @@ -947,20 +1354,28 @@

      Arithmetic Instructions

      -

      Builds a negation instruction with the given value as an operand.

      +

      Builds a cast operation from a value of pointer type to any other +integral, pointer, or vector of integral/pointer type.

      -

      Whether an integer or floating point negate instruction is built is -determined by the type of the given value. Providing an operand that is -neither an integer nor a floating value is a fatal condition.

      +

      There are a number of restrictions on the form of the input value and +destination type. The source value of a pointer cast must be either a +pointer or a vector of pointers. The destination type must either be +an integer type, a pointer type, or a vector type with integral or pointer +element type.

      + +

      If the destination type is an integral type or a vector of integral +elements, this builds a ptrtoint instruction. Else, if the destination +is a pointer type or vector of pointer type, and it has an address space +that differs from the address space of the source value, an +addrspacecast instruction is built. If none of these are true, a +bitcast instruction is built.

      Declaration

      Swift

      -
      public func buildNeg(_ value: IRValue,
      -                       overflowBehavior: OverflowBehavior = .default,
      -                       name: String = "") -> IRValue
      +
      public func buildPointerCast(of value: IRValue, to type: IRType, name: String = "") -> IRValue
      @@ -976,20 +1391,20 @@

      Parameters

      -

      The value to negate.

      +

      The value to cast. The value must have pointer type.

      - overflowBehavior + type
      -

      Should overflow occur, specifies the -behavior of the program.

      +

      The destination type to cast to. This must be a pointer type, +integer type, or vector of the same.

      @@ -1010,7 +1425,8 @@

      Parameters

      Return Value

      -

      A value representing the negation of the given value.

      +

      A value representing the result of casting the given value to +the given destination type using the appropriate pointer cast operation.

    @@ -1018,9 +1434,9 @@

    Return Value

  • @@ -1028,10 +1444,196 @@

    Return Value

    -

    Builds an add instruction with the given values as operands.

    +

    Builds a cast operation from a value of integral type to given integral +type by zero-extension, sign-extension, bitcast, or truncation +as necessary.

    -

    Whether an integer or floating point add instruction is built is -determined by the type of the first given value. Providing operands that +

    +
    +

    Declaration

    +
    +

    Swift

    +
    public func buildIntCast(of value: IRValue, to type: IntType, signed: Bool = true, name: String = "") -> IRValue
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + + + + + +
    + + value + + +
    +

    The value to cast.

    +
    +
    + + type + + +
    +

    The destination integer type to cast to.

    +
    +
    + + signed + + +
    +

    If true, if an extension is required it will be a +sign-extension. Else, all required extensions will be +zero-extensions.

    +
    +
    + + name + + +
    +

    The name for the newly inserted instruction.

    +
    +
    +
    +
    +

    Return Value

    +

    A value reprresenting the result of casting the given value to +the given destination integer type using the appropriate +integral cast operation.

    +
    +
    +
    +
  • + + +
    +
    + + +
    + +

    Arithmetic Instructions

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Build a negation instruction with the given value as an operand.

      + +

      Whether an integer or floating point negate instruction is built is +determined by the type of the given value. Providing an operand that is +neither an integer nor a floating value is a fatal condition.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildNeg(_ value: IRValue,
      +                     overflowBehavior: OverflowBehavior = .default,
      +                     name: String = "") -> IRValue
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + value + + +
      +

      The value to negate.

      +
      +
      + + overflowBehavior + + +
      +

      Should overflow occur, specifies the +behavior of the program.

      +
      +
      + + name + + +
      +

      The name for the newly inserted instruction.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing the negation of the given value.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Build an add instruction with the given values as operands.

      + +

      Whether an integer or floating point add instruction is built is +determined by the type of the first given value. Providing operands that are neither integers nor floating values is a fatal condition.

      @@ -1039,9 +1641,9 @@

      Return Value

      Declaration

      Swift

      -
      public func buildAdd(_ lhs: IRValue, _ rhs: IRValue,
      -                       overflowBehavior: OverflowBehavior = .default,
      -                       name: String = "") -> IRValue
      +
      public func buildAdd(_ lhs: IRValue, _ rhs: IRValue,
      +                     overflowBehavior: OverflowBehavior = .default,
      +                     name: String = "") -> IRValue
      @@ -1111,9 +1713,9 @@

      Return Value

    • @@ -1121,7 +1723,7 @@

      Return Value

      -

      Builds a subtract instruction with the given values as operands.

      +

      Build a subtract instruction with the given values as operands.

      Whether an integer or floating point subtract instruction is built is determined by the type of the first given value. Providing operands that @@ -1132,9 +1734,9 @@

      Return Value

      Declaration

      Swift

      -
      public func buildSub(_ lhs: IRValue, _ rhs: IRValue,
      -                       overflowBehavior: OverflowBehavior = .default,
      -                       name: String = "") -> IRValue
      +
      public func buildSub(_ lhs: IRValue, _ rhs: IRValue,
      +                     overflowBehavior: OverflowBehavior = .default,
      +                     name: String = "") -> IRValue
      @@ -1204,9 +1806,9 @@

      Return Value

    • @@ -1214,7 +1816,7 @@

      Return Value

      -

      Builds a multiply instruction with the given values as operands.

      +

      Build a multiply instruction with the given values as operands.

      Whether an integer or floating point multiply instruction is built is determined by the type of the first given value. Providing operands that @@ -1225,9 +1827,9 @@

      Return Value

      Declaration

      Swift

      -
      public func buildMul(_ lhs: IRValue, _ rhs: IRValue,
      -                       overflowBehavior: OverflowBehavior = .default,
      -                       name: String = "") -> IRValue
      +
      public func buildMul(_ lhs: IRValue, _ rhs: IRValue,
      +                     overflowBehavior: OverflowBehavior = .default,
      +                     name: String = "") -> IRValue
      @@ -1297,9 +1899,9 @@

      Return Value

    • @@ -1319,9 +1921,9 @@

      Return Value

      Declaration

      Swift

      -
      public func buildRem(_ lhs: IRValue, _ rhs: IRValue,
      -                       signed: Bool = true,
      -                       name: String = "") -> IRValue
      +
      public func buildRem(_ lhs: IRValue, _ rhs: IRValue,
      +                     signed: Bool = true,
      +                     name: String = "") -> IRValue
      @@ -1392,9 +1994,9 @@

      Return Value

    • @@ -1414,9 +2016,9 @@

      Return Value

      Declaration

      Swift

      -
      public func buildDiv(_ lhs: IRValue, _ rhs: IRValue,
      -                       signed: Bool = true, exact: Bool = false,
      -                       name: String = "") -> IRValue
      +
      public func buildDiv(_ lhs: IRValue, _ rhs: IRValue,
      +                     signed: Bool = true, exact: Bool = false,
      +                     name: String = "") -> IRValue
      @@ -1501,9 +2103,9 @@

      Return Value

    • @@ -1513,17 +2115,24 @@

      Return Value

      Build an integer comparison between the two provided values using the given predicate.

      +
      +

      Precondition

      + Arguments must be integer or pointer or integer vector typed + +
      +

      Precondition

      +

      lhs.type == rhs.type

      -

      Attempting to compare operands that are not integers is a fatal condition.

      +

      Declaration

      Swift

      -
      public func buildICmp(_ lhs: IRValue, _ rhs: IRValue,
      -                        _ predicate: IntPredicate,
      -                        name: String = "") -> IRValue
      +
      public func buildICmp(_ lhs: IRValue, _ rhs: IRValue,
      +                      _ predicate: IntPredicate,
      +                      name: String = "") -> IRValue
      @@ -1593,9 +2202,9 @@

      Return Value

    • @@ -1613,9 +2222,9 @@

      Return Value

      Declaration

      Swift

      -
      public func buildFCmp(_ lhs: IRValue, _ rhs: IRValue,
      -                        _ predicate: RealPredicate,
      -                        name: String = "") -> IRValue
      +
      public func buildFCmp(_ lhs: IRValue, _ rhs: IRValue,
      +                      _ predicate: RealPredicate,
      +                      name: String = "") -> IRValue
      @@ -1688,17 +2297,19 @@

      Return Value

      - -

      Logical Instructions

      -
      +
      + +

      Logical Instructions

      +

      +
      • @@ -1706,14 +2317,14 @@

        Logical Instructions

        -

        Builds a bitwise logical not with the given value as an operand.

        +

        Build a bitwise logical not with the given value as an operand.

        Declaration

        Swift

        -
        public func buildNot(_ val: IRValue, name: String = "") -> IRValue
        +
        public func buildNot(_ val: IRValue, name: String = "") -> IRValue
        @@ -1758,9 +2369,9 @@

        Return Value

      • @@ -1768,14 +2379,14 @@

        Return Value

        -

        Builds a bitwise logical exclusive OR with the given values as operands.

        +

        Build a bitwise logical exclusive OR with the given values as operands.

        Declaration

        Swift

        -
        public func buildXor(_ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue
        +
        public func buildXor(_ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue
        @@ -1833,9 +2444,9 @@

        Return Value

      • @@ -1843,14 +2454,14 @@

        Return Value

        -

        Builds a bitwise logical OR with the given values as operands.

        +

        Build a bitwise logical OR with the given values as operands.

        Declaration

        Swift

        -
        public func buildOr(_ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue
        +
        public func buildOr(_ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue
        @@ -1908,9 +2519,9 @@

        Return Value

      • @@ -1918,14 +2529,14 @@

        Return Value

        -

        Builds a bitwise logical AND with the given values as operands.

        +

        Build a bitwise logical AND with the given values as operands.

        Declaration

        Swift

        -
        public func buildAnd(_ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue
        +
        public func buildAnd(_ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue
        @@ -1983,9 +2594,9 @@

        Return Value

      • @@ -1993,7 +2604,7 @@

        Return Value

        -

        Builds a left-shift instruction of the first value by an amount in the +

        Build a left-shift instruction of the first value by an amount in the second value.

        @@ -2001,8 +2612,8 @@

        Return Value

        Declaration

        Swift

        -
        public func buildShl(_ lhs: IRValue, _ rhs: IRValue,
        -                       name: String = "") -> IRValue
        +
        public func buildShl(_ lhs: IRValue, _ rhs: IRValue,
        +                     name: String = "") -> IRValue
        @@ -2060,9 +2671,9 @@

        Return Value

      • @@ -2070,7 +2681,7 @@

        Return Value

        -

        Builds a right-shift instruction of the first value by an amount in the +

        Build a right-shift instruction of the first value by an amount in the second value. If isArithmetic is true the value of the first operand is bitshifted with sign extension. Else the value is bitshifted with zero-fill.

        @@ -2080,9 +2691,9 @@

        Return Value

        Declaration

        Swift

        -
        public func buildShr(_ lhs: IRValue, _ rhs: IRValue,
        -                       isArithmetic: Bool = false,
        -                       name: String = "") -> IRValue
        +
        public func buildShr(_ lhs: IRValue, _ rhs: IRValue,
        +                     isArithmetic: Bool = false,
        +                     name: String = "") -> IRValue
        @@ -2156,17 +2767,19 @@

        Return Value

        - -

        Conditional Instructions

        -
        +
        + +

        Conditional Instructions

        +

        +
        • @@ -2182,7 +2795,7 @@

          Conditional Instructions

          Declaration

          Swift

          -
          public func buildPhi(_ type: IRType, name: String = "") -> PhiNode
          +
          public func buildPhi(_ type: IRType, name: String = "") -> PhiNode
          @@ -2227,9 +2840,9 @@

          Return Value

        • @@ -2245,7 +2858,7 @@

          Return Value

          Declaration

          Swift

          -
          public func buildSelect(_ cond: IRValue, then: IRValue, else: IRValue, name: String = "") -> IRValue
          +
          public func buildSelect(_ cond: IRValue, then: IRValue, else: IRValue, name: String = "") -> IRInstruction
          @@ -2315,9 +2928,9 @@

          Return Value

        • @@ -2328,16 +2941,25 @@

          Return Value

          Build a branch table that branches on the given value with the given default basic block.

          -

          The ‘switch‘ instruction is used to transfer control flow to one of -several different places. It is a generalization of the ‘br‘ instruction, +

          The switch instruction is used to transfer control flow to one of +several different places. It is a generalization of the br instruction, allowing a branch to occur to one of many possible destinations.

          +

          This function returns a value that acts as a representation of the branch +table for the switch instruction. When the switch instruction is +executed, this table is searched for the given value. If the value is +found, control flow is transferred to the corresponding destination; +otherwise, control flow is transferred to the default destination +specified by the else block.

          + +

          To add branches to the switch table, see Switch.addCase(_:_:).

          +

          Declaration

          Swift

          -
          public func buildSwitch(_ value: IRValue, else: BasicBlock, caseCount: Int) -> Switch
          +
          public func buildSwitch(_ value: IRValue, else: BasicBlock, caseCount: Int) -> Switch
          @@ -2398,17 +3020,19 @@

          Return Value

          - -

          Declaration Instructions

          -
          +
          + +

          Declaration Instructions

          +

          +
          • @@ -2423,7 +3047,7 @@

            Declaration Instructions

            Declaration

            Swift

            -
            public func addFunction(_ name: String, type: FunctionType) -> Function
            +
            public func addFunction(_ name: String, type: FunctionType) -> Function
            @@ -2468,9 +3092,9 @@

            Return Value

          • @@ -2485,7 +3109,7 @@

            Return Value

            Declaration

            Swift

            -
            public func createStruct(name: String, types: [IRType]? = nil, isPacked: Bool = false) -> StructType
            +
            public func createStruct(name: String, types: [IRType]? = nil, isPacked: Bool = false) -> StructType
            @@ -2546,17 +3170,19 @@

            Return Value

            - -

            Terminator Instructions

            -
            +
            + +

            Terminator Instructions

            +

            +
            • @@ -2566,12 +3192,19 @@

              Terminator Instructions

              Build an unconditional branch to the given basic block.

              +

              The br instruction is used to cause control flow to transfer to a +different basic block in the current function. There are two forms of this +instruction, corresponding to a conditional branch and an unconditional +branch. To build a conditional branch, see +buildCondBr(condition:then:else:).

              +

              Declaration

              Swift

              -
              public func buildBr(_ block: BasicBlock) -> IRValue
              +
              @discardableResult
              +public func buildBr(_ block: BasicBlock) -> IRInstruction
              @@ -2604,9 +3237,9 @@

              Return Value

            • @@ -2617,12 +3250,19 @@

              Return Value

              Build a condition branch that branches to the first basic block if the provided condition is true, otherwise to the second basic block.

              +

              The br instruction is used to cause control flow to transfer to a +different basic block in the current function. There are two forms of this +instruction, corresponding to a conditional branch and an unconditional +branch. To build an unconditional branch, see buildBr(_:).

              +

              Declaration

              Swift

              -
              public func buildCondBr(condition: IRValue, then: BasicBlock, `else`: BasicBlock) -> IRValue
              +
              @discardableResult
              +public func buildCondBr(
              +  condition: IRValue, then: BasicBlock, `else`: BasicBlock) -> IRInstruction
              @@ -2682,9 +3322,9 @@

              Return Value

            • @@ -2694,12 +3334,21 @@

              Return Value

              Build an indirect branch to a label within the current function.

              +

              The indirectbr instruction implements an indirect branch to a label +within the current function, whose address is specified by the address +parameter.

              + +

              All possible destination blocks must be listed in the destinations list, +otherwise this instruction has undefined behavior. This implies that jumps +to labels defined in other functions have undefined behavior as well.

              +

              Declaration

              Swift

              -
              public func buildIndirectBr(address: BasicBlock.Address, destinations: [BasicBlock]) -> IRValue
              +
              @discardableResult
              +public func buildIndirectBr(address: BasicBlock.Address, destinations: [BasicBlock]) -> IRInstruction
              @@ -2746,9 +3395,9 @@

              Return Value

            • @@ -2756,15 +3405,23 @@

              Return Value

              -

              Builds a return from the current function back to the calling function +

              Build a return from the current function back to the calling function with the given value.

              +

              Returning a value with a type that does not correspond to the return +type of the current function is a fatal condition.

              + +

              There are two forms of the ret instruction: one that returns a value and +then causes control flow, and one that just causes control flow to occur. +To build the ret that does not return a value use buildRetVoid().

              +

              Declaration

              Swift

              -
              public func buildRet(_ val: IRValue) -> IRValue
              +
              @discardableResult
              +public func buildRet(_ val: IRValue) -> IRInstruction
              @@ -2797,9 +3454,9 @@

              Return Value

            • @@ -2807,14 +3464,22 @@

              Return Value

              -

              Builds a void return from the current function.

              +

              Build a void return from the current function.

              + +

              If the current function does not have a Void return value, failure to +return a falue is a fatal condition.

              + +

              There are two forms of the ret instruction: one that returns a value and +then causes control flow, and one that just causes control flow to occur. +To build the ret that returns a value use buildRet(_:).

              Declaration

              Swift

              -
              public func buildRetVoid() -> IRValue
              +
              @discardableResult
              +public func buildRetVoid() -> IRInstruction
              @@ -2828,9 +3493,9 @@

              Return Value

            • @@ -2838,14 +3503,20 @@

              Return Value

              -

              Builds an unreachable instruction in the current function.

              +

              Build an unreachable instruction in the current function.

              + +

              The unreachable instruction has no defined semantics. This instruction +is used to inform the optimizer that a particular portion of the code is +not reachable. This can be used to indicate that the code after a +no-return function cannot be reached, and other facts.

              Declaration

              Swift

              -
              public func buildUnreachable() -> IRValue
              +
              @discardableResult
              +public func buildUnreachable() -> IRInstruction
              @@ -2859,9 +3530,9 @@

              Return Value

            • @@ -2877,7 +3548,8 @@

              Return Value

              Declaration

              Swift

              -
              public func buildRetAggregate(of values: [IRValue]) -> IRValue
              +
              @discardableResult
              +public func buildRetAggregate(of values: [IRValue]) -> IRInstruction
              @@ -2893,7 +3565,8 @@

              Parameters

              -

              The values to insert as members of the returned aggregate.

              +

              The values to insert as members of the returned +aggregate.

              @@ -2910,9 +3583,9 @@

              Return Value

            • @@ -2928,7 +3601,7 @@

              Return Value

              Declaration

              Swift

              -
              public func buildCall(_ fn: IRValue, args: [IRValue], name: String = "") -> Call
              +
              public func buildCall(_ fn: IRValue, args: [IRValue], name: String = "") -> Call
              @@ -2988,17 +3661,19 @@

              Return Value

              - -

              Exception Handling Instructions

              -
              +
              + +

              Exception Handling Instructions

              +

              +
            • @@ -3267,9 +3948,9 @@

              Return Value

            • @@ -3278,7 +3959,7 @@

              Return Value

              Build a va_arg instruction to access arguments passed through the -variable argument area of a function call.

              +“variable argument” area of a function call.

              This instruction is used to implement the va_arg macro in C.

              @@ -3287,7 +3968,7 @@

              Return Value

              Declaration

              Swift

              -
              public func buildVAArg(_ list: IRValue, type: IRType, name: String = "") -> IRValue
              +
              public func buildVAArg(_ list: IRValue, type: IRType, name: String = "") -> IRValue
              @@ -3348,17 +4029,19 @@

              Return Value

              - -

              Memory Access Instructions

              -
              +
              + +

              Memory Access Instructions

              +

              +
              • @@ -3369,12 +4052,25 @@

                Memory Access Instructions

                Build an alloca to allocate stack memory to hold a value of the given type.

                +

                The alloca instruction allocates sizeof(<type>)*count bytes of +memory on the runtime stack, returning a pointer of the appropriate type +to the program. If count is specified, it is the number of elements +allocated, otherwise count is defaulted to be one. If a constant +alignment is specified, the value result of the allocation is guaranteed +to be aligned to at least that boundary. The alignment may not be +greater than 1 << 29. If not specified, or if zero, the target will +choose a default value that is convenient and compatible with the type.

                + +

                The returned value is allocated in the address space specified in the data layout string for the target. If +no such value is specified, the value is allocated in the default address space.

                +

                Declaration

                Swift

                -
                public func buildAlloca(type: IRType, name: String = "") -> IRValue
                +
                public func buildAlloca(type: IRType, count: IRValue? = nil,
                +                        alignment: Alignment = .zero, name: String = "") -> IRInstruction
                @@ -3395,6 +4091,31 @@

                Parameters

              + + + + count + + + +
              +

              An optional number of slots to allocate, to simulate a + C array.

              +
              + + + + + + alignment + + + +
              +

              The alignment of the access.

              +
              + + @@ -3420,9 +4141,9 @@

              Return Value

            • @@ -3433,44 +4154,16 @@

              Return Value

              Build a store instruction that stores the first value into the location given in the second value.

              -
              -
              -

              Declaration

              -
              -

              Swift

              -
              public func buildStore(_ val: IRValue, to ptr: IRValue) -> IRValue
              - -
              -
              -
              -

              Return Value

              -

              A value representing void.

              -
              -
            • -
              -
            • -
            • -
              - - - - buildLoad(_:name:) - -
              -
              -
              -
              -
              -
              -

              Builds a load instruction that loads a value from the location in the -given value.

              +

              If alignment is not specified, or if zero, the target will choose a default +value that is convenient and compatible with the type.

              Declaration

              Swift

              -
              public func buildLoad(_ ptr: IRValue, name: String = "") -> IRValue
              +
              @discardableResult
              +public func buildStore(_ val: IRValue, to ptr: IRValue, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false, alignment: Alignment = .zero) -> IRInstruction
              @@ -3478,6 +4171,18 @@

              Declaration

              Parameters

              + + + + - -
              + + val + + +
              +

              The source value.

              +
              +
              @@ -3486,28 +4191,168 @@

              Parameters

              -

              The pointer value to load from.

              +

              The destination pointer to store into.

              - name + ordering
              -

              The name for the newly inserted instruction.

              +

              The ordering effect of the fence for this store, +if any. Defaults to a nonatomic store.

              -
              -
              -

              Return Value

              -

              A value representing the result of a load from the given + + + + volatile + + + +

              +

              Whether this is a store to a volatile memory location.

              +
              + + + + + + alignment + + + +
              +

              The alignment of the access.

              +
              + + + + +
              +
              +

              Return Value

              +

              A value representing void.

              +
              +
            • +
              +
            • +
            • + +
              +
              +
              +
              +
              +

              Build a load instruction that loads a value from the location in the +given value.

              + +

              If alignment is not specified, or if zero, the target will choose a default +value that is convenient and compatible with the type.

              + +
              +
              +

              Declaration

              +
              +

              Swift

              +
              public func buildLoad(_ ptr: IRValue, type: IRType, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false, alignment: Alignment = .zero, name: String = "") -> IRInstruction
              + +
              +
              +
              +

              Parameters

              + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              + + ptr + + +
              +

              The pointer value to load from.

              +
              +
              + + type + + +
              +

              The type of value loaded from the given pointer.

              +
              +
              + + ordering + + +
              +

              The ordering effect of the fence for this load, +if any. Defaults to a nonatomic load.

              +
              +
              + + volatile + + +
              +

              Whether this is a load from a volatile memory location.

              +
              +
              + + alignment + + +
              +

              The alignment of the access.

              +
              +
              + + name + + +
              +

              The name for the newly inserted instruction.

              +
              +
              +
              +
              +

              Return Value

              +

              A value representing the result of a load from the given pointer value.

              @@ -3516,9 +4361,9 @@

              Return Value

            • @@ -3526,7 +4371,7 @@

              Return Value

              -

              Builds a GEP (Get Element Pointer) instruction with a resultant value +

              Build a GEP (Get Element Pointer) instruction with a resultant value that is undefined if the address is outside the actual underlying allocated object and not the address one-past-the-end.

              @@ -3539,7 +4384,7 @@

              Return Value

              Declaration

              Swift

              -
              public func buildInBoundsGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue
              +
              public func buildInBoundsGEP(_ ptr: IRValue, type: IRType, indices: [IRValue], name: String = "") -> IRValue
              @@ -3559,6 +4404,18 @@

              Parameters

              + + + + type + + + +
              +

              The type used to calculate pointer offsets.

              +
              + + @@ -3598,9 +4455,9 @@

              Return Value

            • @@ -3608,7 +4465,7 @@

              Return Value

              -

              Builds a GEP (Get Element Pointer) instruction.

              +

              Build a GEP (Get Element Pointer) instruction.

              The GEP instruction is often the source of confusion. LLVM provides a document to answer questions @@ -3619,7 +4476,7 @@

              Return Value

              Declaration

              Swift

              -
              public func buildGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue
              +
              public func buildGEP(_ ptr: IRValue, type: IRType, indices: [IRValue], name: String = "") -> IRValue
              @@ -3639,6 +4496,18 @@

              Parameters

              + + + + type + + + +
              +

              The type used to calculate pointer offsets.

              +
              + + @@ -3678,9 +4547,9 @@

              Return Value

            • @@ -3688,15 +4557,15 @@

              Return Value

              -

              Builds a GEP (Get Element Pointer) instruction suitable for indexing into -a struct.

              +

              Build a GEP (Get Element Pointer) instruction suitable for indexing into +a struct of a given type.

              Declaration

              Swift

              -
              public func buildStructGEP(_ ptr: IRValue, index: Int, name: String = "") -> IRValue
              +
              public func buildStructGEP(_ ptr: IRValue, type: IRType, index: Int, name: String = "") -> IRValue
              @@ -3716,6 +4585,18 @@

              Parameters

              + + + + type + + + +
              +

              The type of the struct to index into.

              +
              + + @@ -3754,9 +4635,9 @@

              Return Value

            • @@ -3764,16 +4645,26 @@

              Return Value

              -

              Builds an ExtractValue instruction to retrieve an indexed value from a +

              Build an ExtractValue instruction to retrieve an indexed value from a struct or array value.

              +

              extractvalue function like a GEP, but has different indexing semantics:

              +
              +

              Since

              + Since the value being indexed is not a pointer, the first index is +omitted and assumed to be zero. + +
                +
              • Not only struct indices but also array indices must be in bounds.

              • +
              +

              Declaration

              Swift

              -
              public func buildExtractValue(_ value: IRValue, index: Int,
              -                                  name: String = "") -> IRValue
              +
              public func buildExtractValue(_ value: IRValue, index: Int,
              +                              name: String = "") -> IRValue
              @@ -3821,17 +4712,19 @@

              Return Value

              - -

              Null Test Instructions

              -
              +
              + +

              Null Test Instructions

              +

              +
              • @@ -3839,7 +4732,7 @@

                Null Test Instructions

                -

                Builds a comparision instruction that returns whether the given operand is +

                Build a comparision instruction that returns whether the given operand is null.

                @@ -3847,7 +4740,7 @@

                Null Test Instructions

                Declaration

                Swift

                -
                public func buildIsNull(_ val: IRValue, name: String = "") -> IRValue
                +
                public func buildIsNull(_ val: IRValue, name: String = "") -> IRValue
                @@ -3893,9 +4786,9 @@

                Return Value

              • @@ -3903,7 +4796,7 @@

                Return Value

                -

                Builds a comparision instruction that returns whether the given operand is +

                Build a comparision instruction that returns whether the given operand is not null.

                @@ -3911,7 +4804,7 @@

                Return Value

                Declaration

                Swift

                -
                public func buildIsNotNull(_ val: IRValue, name: String = "") -> IRValue
                +
                public func buildIsNotNull(_ val: IRValue, name: String = "") -> IRValue
                @@ -3960,17 +4853,19 @@

                Return Value

                - -

                Conversion Instructions

                -
                +
                + +

                Conversion Instructions

                +

                +
                • @@ -3978,7 +4873,7 @@

                  Conversion Instructions

                  -

                  Builds an instruction that either performs a truncation or a bitcast of +

                  Build an instruction that either performs a truncation or a bitcast of the given value to a value of the given type.

                  @@ -3986,7 +4881,7 @@

                  Conversion Instructions

                  Declaration

                  Swift

                  -
                  public func buildTruncOrBitCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  +
                  public func buildTruncOrBitCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  @@ -4044,9 +4939,9 @@

                  Return Value

                • @@ -4054,7 +4949,7 @@

                  Return Value

                  -

                  Builds an instruction that either performs a zero extension or a bitcast of +

                  Build an instruction that either performs a zero extension or a bitcast of the given value to a value of the given type with a wider width.

                  @@ -4062,7 +4957,7 @@

                  Return Value

                  Declaration

                  Swift

                  -
                  public func buildZExtOrBitCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  +
                  public func buildZExtOrBitCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  @@ -4120,9 +5015,9 @@

                  Return Value

                • @@ -4130,15 +5025,23 @@

                  Return Value

                  -

                  Builds a bitcast instruction to convert the given value to a value of the +

                  Build a bitcast instruction to convert the given value to a value of the given type by just copying the bit pattern.

                  +

                  The bitcast instruction is always a no-op cast because no bits change +with this conversion. The conversion is done as if the value had been +stored to memory and read back as the given type. Pointer (or vector of +pointer) types may only be converted to other pointer (or vector of +pointer) types with the same address space through this instruction. To +convert pointers to other types, see buildIntToPtr(_:type:name:) or +buildPtrToInt(_:type:name:).

                  +

                  Declaration

                  Swift

                  -
                  public func buildBitCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  +
                  public func buildBitCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  @@ -4196,9 +5099,9 @@

                  Return Value

                • @@ -4206,7 +5109,7 @@

                  Return Value

                  -

                  Builds a cast instruction to convert the given floating-point value to a +

                  Build a cast instruction to convert the given floating-point value to a value of the given type.

                  @@ -4214,7 +5117,7 @@

                  Return Value

                  Declaration

                  Swift

                  -
                  public func buildFPCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  +
                  public func buildFPCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  @@ -4272,9 +5175,9 @@

                  Return Value

                • @@ -4282,9 +5185,18 @@

                  Return Value

                  -

                  Builds an address space cast instruction that converts a pointer value +

                  Build an address space cast instruction that converts a pointer value to a given type in a different address space.

                  +

                  The addrspacecast instruction can be a no-op cast or a complex value +modification, depending on the target and the address space pair. Pointer +conversions within the same address space must be performed with the +bitcast instruction. Note that if the address space conversion is legal +then both result and operand refer to the same memory location.

                  + +

                  This instruction must be used in lieu of a bitcast even if the cast is between +types of the same size.

                  +

                  The address spaces of the value and the destination pointer types must be distinct.

                  @@ -4293,7 +5205,7 @@

                  Return Value

                  Declaration

                  Swift

                  -
                  public func buildAddrSpaceCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  +
                  public func buildAddrSpaceCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  @@ -4303,9 +5215,9 @@

                  Declaration

                • @@ -4313,7 +5225,7 @@

                  Declaration

                  -

                  Builds a truncate instruction to truncate the given value to the given +

                  Build a truncate instruction to truncate the given value to the given type with a shorter width.

                  @@ -4321,7 +5233,7 @@

                  Declaration

                  Declaration

                  Swift

                  -
                  public func buildTrunc(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  +
                  public func buildTrunc(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  @@ -4379,9 +5291,9 @@

                  Return Value

                • @@ -4389,7 +5301,7 @@

                  Return Value

                  -

                  Builds a sign extension instruction to sign extend the given value to +

                  Build a sign extension instruction to sign extend the given value to the given type with a wider width.

                  @@ -4397,7 +5309,7 @@

                  Return Value

                  Declaration

                  Swift

                  -
                  public func buildSExt(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  +
                  public func buildSExt(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  @@ -4455,9 +5367,9 @@

                  Return Value

                • @@ -4465,7 +5377,7 @@

                  Return Value

                  -

                  Builds a zero extension instruction to zero extend the given value to the +

                  Build a zero extension instruction to zero extend the given value to the given type with a wider width.

                  @@ -4473,7 +5385,7 @@

                  Return Value

                  Declaration

                  Swift

                  -
                  public func buildZExt(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  +
                  public func buildZExt(_ val: IRValue, type: IRType, name: String = "") -> IRValue
                  @@ -4531,9 +5443,9 @@

                  Return Value

                • @@ -4541,15 +5453,22 @@

                  Return Value

                  -

                  Builds an integer-to-pointer instruction to convert the given value to the +

                  Build an integer-to-pointer instruction to convert the given value to the given pointer type.

                  +

                  The inttoptr instruction converts the given value to the given pointer +type by applying either a zero extension or a truncation depending on the +size of the integer value. If value is larger than the size of a pointer +then a truncation is done. If value is smaller than the size of a pointer +then a zero extension is done. If they are the same size, nothing is done +(no-op cast).

                  +

                  Declaration

                  Swift

                  -
                  public func buildIntToPtr(_ val: IRValue, type: PointerType, name: String = "") -> IRValue
                  +
                  public func buildIntToPtr(_ val: IRValue, type: PointerType, name: String = "") -> IRValue
                  @@ -4607,9 +5526,9 @@

                  Return Value

                • @@ -4617,15 +5536,23 @@

                  Return Value

                  -

                  Builds a pointer-to-integer instruction to convert the given pointer value +

                  Build a pointer-to-integer instruction to convert the given pointer value to the given integer type.

                  +

                  The ptrtoint instruction converts the given pointer value to the given +integer type by interpreting the pointer value as an integer and either +truncating or zero extending that value to the size of the integer type. +If the pointer value is smaller than the integer type then a zero +extension is done. If the pointer value is larger than the integer type +then a truncation is done. If they are the same size, then nothing is done +(no-op cast) other than a type change.

                  +

                  Declaration

                  Swift

                  -
                  public func buildPtrToInt(_ val: IRValue, type: IntType, name: String = "") -> IRValue
                  +
                  public func buildPtrToInt(_ val: IRValue, type: IntType, name: String = "") -> IRValue
                  @@ -4683,9 +5610,9 @@

                  Return Value

                • @@ -4693,7 +5620,7 @@

                  Return Value

                  -

                  Builds an integer-to-floating instruction to convert the given integer +

                  Build an integer-to-floating instruction to convert the given integer value to the given floating type.

                  @@ -4701,7 +5628,7 @@

                  Return Value

                  Declaration

                  Swift

                  -
                  public func buildIntToFP(_ val: IRValue, type: FloatType, signed: Bool, name: String = "") -> IRValue
                  +
                  public func buildIntToFP(_ val: IRValue, type: FloatType, signed: Bool, name: String = "") -> IRValue
                  @@ -4771,9 +5698,9 @@

                  Return Value

                • @@ -4781,7 +5708,7 @@

                  Return Value

                  -

                  Builds a floating-to-integer instruction to convert the given floating +

                  Build a floating-to-integer instruction to convert the given floating value to the given integer type.

                  @@ -4789,7 +5716,7 @@

                  Return Value

                  Declaration

                  Swift

                  -
                  public func buildFPToInt(_ val: IRValue, type: IntType, signed: Bool, name: String = "") -> IRValue
                  +
                  public func buildFPToInt(_ val: IRValue, type: IntType, signed: Bool, name: String = "") -> IRValue
                  @@ -4859,9 +5786,9 @@

                  Return Value

                • @@ -4869,15 +5796,19 @@

                  Return Value

                  -

                  Builds a constant expression that returns the alignment of the given type -in bytes.

                  +

                  Build an expression that returns the difference between two pointer +values, dividing out the size of the pointed-to objects.

                  + +

                  This is intended to implement C-style pointer subtraction. As such, the +pointers must be appropriately aligned for their element types and +pointing into the same object.

                  Declaration

                  Swift

                  -
                  public func buildAlignOf(_ val: IRType) -> IRValue
                  +
                  public func buildPointerDifference(_ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue
                  @@ -4888,12 +5819,36 @@

                  Parameters

                  - val + lhs
                  -

                  The type to evaluate the alignment of.

                  +

                  The first pointer (the minuend).

                  +
                  + + + + + + rhs + + + +
                  +

                  The second pointer (the subtrahend).

                  +
                  + + + + + + name + + + +
                  +

                  The name for the newly inserted instruction.

                  @@ -4902,18 +5857,31 @@

                  Parameters

                  Return Value

                  -

                  An integer value representing the alignment of the given type -in bytes.

                  +

                  A IRValue representing a 64-bit integer value of the difference +of the two pointer values modulo the size of the pointed-to objects.

                • +
                +
              +
              +
              + + +
              + +

              Type Information

              +

              +
              +
              +
              • @@ -4921,15 +5889,15 @@

                Return Value

                -

                Builds a constant expression that returns the size of the given type in -bytes.

                +

                Build a constant expression that returns the alignment of the given type +in bytes.

                Declaration

                Swift

                -
                public func buildSizeOf(_ val: IRType) -> IRValue
                +
                public func buildAlignOf(_ val: IRType) -> IRValue
                @@ -4945,7 +5913,7 @@

                Parameters

                -

                The type to evaluate the size of.

                +

                The type to evaluate the alignment of.

                @@ -4954,8 +5922,8 @@

                Parameters

                Return Value

                -

                An integer value representing the size of the given type in -bytes.

                +

                An integer value representing the alignment of the given type +in bytes.

        @@ -4963,9 +5931,9 @@

        Return Value

      • @@ -4973,19 +5941,15 @@

        Return Value

        -

        Builds an expression that returns the difference between two pointer -values, dividing out the size of the pointed-to objects.

        - -

        This is intended to implement C-style pointer subtraction. As such, the -pointers must be appropriately aligned for their element types and -pointing into the same object.

        +

        Build a constant expression that returns the size of the given type in +bytes.

        Declaration

        Swift

        -
        public func buildPointerDifference(_ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue
        +
        public func buildSizeOf(_ val: IRType) -> IRValue
        @@ -4996,36 +5960,12 @@

        Parameters

        - lhs - - - -
        -

        The first pointer (the minuend).

        -
        - - - - - - rhs + val
        -

        The second pointer (the subtrahend).

        -
        - - - - - - name - - - -
        -

        The name for the newly inserted instruction.

        +

        The type to evaluate the size of.

        @@ -5034,8 +5974,8 @@

        Parameters

        Return Value

        -

        A IRValue representing a 64-bit integer value of the difference -of the two pointer values modulo the size of the pointed-to objects.

        +

        An integer value representing the size of the given type in +bytes.

      • @@ -5046,17 +5986,19 @@

        Return Value

        - -

        Atomic Instructions

        -
        +
        + +

        Atomic Instructions

        +

        +
        • @@ -5064,15 +6006,32 @@

          Atomic Instructions

          -

          Builds a fence instruction that introduces happens-before edges between +

          Build a fence instruction that introduces “happens-before” edges between operations.

          +

          A fence A which has (at least) release ordering semantics synchronizes +with a fence B with (at least) acquire ordering semantics if and only +if there exist atomic operations X and Y, both operating on some atomic +object M, such that A is sequenced before X, X modifies M +(either directly or through some side effect of a sequence headed by X), +Y is sequenced before B, and Y observes M. This provides a +happens-before dependency between A and B. Rather than an explicit +fence, one (but not both) of the atomic operations X or Y might +provide a release or acquire (resp.) ordering constraint and still +synchronize-with the explicit fence and establish the happens-before edge.

          + +

          A fence which has sequentiallyConsistent ordering, in addition to having +both acquire and release semantics specified above, participates in +the global program order of other sequentiallyConsistent operations +and/or fences.

          +

          Declaration

          Swift

          -
          public func buildFence(ordering: AtomicOrdering, singleThreaded: Bool = false, name: String = "") -> IRValue
          +
          @discardableResult
          +public func buildFence(ordering: AtomicOrdering, singleThreaded: Bool = false, name: String = "") -> IRInstruction
          @@ -5088,7 +6047,7 @@

          Parameters

          -

          Defines the kind of synchronizes-with edge this +

          Defines the kind of “synchronizes-with” edge this fence adds.

          @@ -5133,9 +6092,9 @@

          Return Value

        • @@ -5143,7 +6102,7 @@

          Return Value

          -

          Builds an atomic compare-and-exchange instruction to atomically modify +

          Build an atomic compare-and-exchange instruction to atomically modify memory. It loads a value in memory and compares it to a given value. If they are equal, it tries to store a new value into the memory.

          @@ -5152,11 +6111,11 @@

          Return Value

          Declaration

          Swift

          -
          public func buildAtomicCmpXchg(
          -    ptr: IRValue, of old: IRValue, to new: IRValue,
          -    successOrdering: AtomicOrdering, failureOrdering: AtomicOrdering,
          -    singleThreaded: Bool = false
          -  ) -> IRValue
          +
          public func buildAtomicCmpXchg(
          +  ptr: IRValue, of old: IRValue, to new: IRValue,
          +  successOrdering: AtomicOrdering, failureOrdering: AtomicOrdering,
          +  singleThreaded: Bool = false
          +) -> IRValue
          @@ -5256,9 +6215,9 @@

          Return Value

        • @@ -5266,17 +6225,17 @@

          Return Value

          -

          Builds an atomic read-modify-write instruction to atomically modify memory.

          +

          Build an atomic read-modify-write instruction to atomically modify memory.

          Declaration

          Swift

          -
          public func buildAtomicRMW(
          -    atomicOp: AtomicReadModifyWriteOperation, ptr: IRValue, value: IRValue,
          -    ordering: AtomicOrdering, singleThreaded: Bool = false
          -  ) -> IRValue
          +
          public func buildAtomicRMW(
          +  atomicOp: AtomicReadModifyWriteOperation, ptr: IRValue, value: IRValue,
          +  ordering: AtomicOrdering, singleThreaded: Bool = false
          +) -> IRValue
          @@ -5328,7 +6287,7 @@

          Parameters

          -

          Defines the kind of synchronizes-with edge this +

          Defines the kind of “synchronizes-with” edge this atomic operation adds.

          @@ -5365,17 +6324,19 @@

          Return Value

          - -

          C Standard Library Instructions

          -
          +
          + +

          C Standard Library Instructions

          +

          +
          • @@ -5383,12 +6344,12 @@

            C Standard Library Instructions

            -

            Builds a call to the C standard library malloc instruction.

            -
            (type *)malloc(sizeof(type));
            +                        

            Build a call to the C standard library malloc instruction.

            +
            (type *)malloc(sizeof(type));
             

            If count is provided, it is equivalent to:

            -
            (type *)malloc(sizeof(type) * count);
            +
            (type *)malloc(sizeof(type) * count);
             
            @@ -5396,8 +6357,8 @@

            C Standard Library Instructions

            Declaration

            Swift

            -
            public func buildMalloc(_ type: IRType, count: IRValue? = nil,
            -                          name: String = "") -> IRValue
            +
            public func buildMalloc(_ type: IRType, count: IRValue? = nil,
            +                        name: String = "") -> IRInstruction
            @@ -5427,7 +6388,7 @@

            Parameters

            An optional number of slots to allocate, to simulate a - C array. This is equivalent to

            + C array.

            @@ -5452,9 +6413,9 @@

            Parameters

          • @@ -5462,7 +6423,7 @@

            Parameters

            -

            Builds a call to the C standard library free function, with the provided +

            Build a call to the C standard library free function, with the provided pointer.

            @@ -5470,7 +6431,8 @@

            Parameters

            Declaration

            Swift

            -
            public func buildFree(_ ptr: IRValue) -> IRValue
            +
            @discardableResult
            +public func buildFree(_ ptr: IRValue) -> IRInstruction
            @@ -5504,19 +6466,21 @@

            Return Value

          - - - -

          Aggregate Instructions

          -
          + + +
          + +

          Memory Intrinsics

          +

          +
          • @@ -5524,15 +6488,26 @@

            Aggregate Instructions

            -

            Builds an instruction to insert a value into a member field in an -aggregate value.

            +

            Builds a call to the llvm.memset.* family of intrinsics to fill a +given block of memory with a given byte value.

            +
            +

            Note

            +

            Unlike the standard function memset defined in libc, +llvm.memset does not return a value and may be volatile. The address +space of the source and destination values need not match.

            + +

            Declaration

            Swift

            -
            public func buildInsertValue(aggregate: IRValue, element: IRValue, index: Int, name: String = "") -> IRValue
            +
            @discardableResult
            +public func buildMemset(
            +  to dest: IRValue, of value: IRValue, length: IRValue,
            +  alignment: Alignment, volatile: Bool = false
            +) -> IRInstruction
            @@ -5543,79 +6518,80 @@

            Parameters

            - aggregate + dest
            -

            A value of array or structure type.

            +

            A pointer value to the destination that will be filled.

            - element + value
            -

            The value to insert.

            +

            A byte value to fill the destination with.

            - index + length
            -

            The index at which at which to insert the value.

            +

            The number of bytes to fill.

            - name + alignment
            -

            The name for the newly inserted instruction.

            +

            The alignment of the destination pointer value.

            +
            + + + + + + volatile + + + +
            +

            If true, builds a volatile llvm.memset intrinsic, else +builds a non-volatile llvm.memset instrinsic. The exact behavior of +volatile memory intrinsics is platform-dependent and should not be +relied upon to perform consistently. For more information, see the +language reference’s section on Volatile Memory +Access.

            -
            -

            Return Value

            -

            A value representing an aggregate that has been updated with -the given value at the given index.

            -
        • -
        -
      • -
        - -
        • @@ -5623,15 +6599,33 @@

          Vector Instructions

          -

          Builds a vector insert instruction to nondestructively insert the given -value into the given vector.

          +

          Builds a call to the llvm.memcpy.* family of intrinsics to copy a block +of memory to a given destination memory location from a given source +memory location.

          +
          +

          Warning

          +

          It is illegal for the destination and source locations to +overlap each other.

          + +
          +

          Note

          +

          Unlike the standard function memcpy defined in libc, +llvm.memcpy does not return a value and may be volatile. The address +space of the source and destination values need not match.

          + +

          Declaration

          Swift

          -
          public func buildInsertElement(vector: IRValue, element: IRValue, index: IRValue, name: String = "") -> IRValue
          +
          @discardableResult
          +public func buildMemCpy(
          +  to dest: IRValue, _ destAlign: Alignment,
          +  from src: IRValue, _ srcAlign: Alignment,
          +  length: IRValue, volatile: Bool = false
          +) -> IRInstruction
          @@ -5642,68 +6636,92 @@

          Parameters

          - vector + dest
          -

          A value of vector type.

          +

          A pointer to the destination that will be filled.

          - element + destAlign
          -

          The value to insert.

          +

          The alignment of the destination pointer value.

          - index + src
          -

          The index at which to insert the value.

          +

          A pointer to the source that will be copied from.

          - name + srcAlign
          -

          The name for the newly inserted instruction.

          +

          The alignment of the source pointer value.

          +
          + + + + + + length + + + +
          +

          The number of bytes to fill.

          +
          + + + + + + volatile + + + +
          +

          If true, builds a volatile llvm.memcpy intrinsic, else +builds a non-volatile llvm.memcpy instrinsic. The exact behavior of +volatile memory intrinsics is platform-dependent and should not be +relied upon to perform consistently. For more information, see the +language reference’s section on Volatile Memory +Access.

          -
          -

          Return Value

          -

          A value representing a vector that has been updated with -the given value at the given index.

          -
      • @@ -5711,15 +6729,31 @@

        Return Value

        -

        Builds an instruction to extract a single scalar element from a vector at -a specified index.

        +

        Builds a call to the llvm.memmove.* family of intrinsics to move a +block of memory to a given destination memory location from a given source +memory location.

        + +

        Unlike llvm.memcpy.*, the destination and source memory locations may +overlap with each other.

        +
        +

        Note

        +

        Unlike the standard function memmove defined in libc, +llvm.memmove does not return a value and may be volatile. The address +space of the source and destination values need not match.

        + +

        Declaration

        Swift

        -
        public func buildExtractElement(vector: IRValue, index: IRValue, name: String = "") -> IRValue
        +
        @discardableResult
        +public func buildMemMove(
        +  to dest: IRValue, _ destAlign: Alignment,
        +  from src: IRValue, _ srcAlign: Alignment,
        +  length: IRValue, volatile: Bool = false
        +) -> IRInstruction
        @@ -5730,55 +6764,105 @@

        Parameters

        - vector + dest
        -

        A value of vector type.

        +

        A pointer to the destination that will be filled.

        - index + destAlign
        -

        The index at which to insert the value.

        +

        The alignment of the destination pointer value.

        - name + src
        -

        The name for the newly inserted instruction.

        +

        A pointer to the source that will be copied from.

        +
        + + + + + + srcAlign + + + +
        +

        The alignment of the source pointer value.

        +
        + + + + + + length + + + +
        +

        The number of bytes to fill.

        +
        + + + + + + volatile + + + +
        +

        If true, builds a volatile llvm.memmove intrinsic, else +builds a non-volatile llvm.memmove instrinsic. The exact behavior of +volatile memory intrinsics is platform-dependent and should not be +relied upon to perform consistently. For more information, see the +language reference’s section on Volatile Memory +Access.

        -
        -

        Return Value

        -

        A value representing a scalar at the given index.

        -
      • +
      +
    • +
      +
      + + +
      + +

      Aggregate Instructions

      +

      +
      +
      +
      • @@ -5786,16 +6870,15 @@

        Return Value

        -

        Builds a vector shuffle instruction to construct a permutation of elements -from the two given input vectors, returning a vector with the same element -type as the inputs and length that is the same as the shuffle mask.

        +

        Build an instruction to insert a value into a member field in an +aggregate value.

        Declaration

        Swift

        -
        public func buildShuffleVector(_ vector1: IRValue, and vector2: IRValue, mask: IRValue, name: String = "") -> IRValue
        +
        public func buildInsertValue(aggregate: IRValue, element: IRValue, index: Int, name: String = "") -> IRValue
        @@ -5806,37 +6889,48 @@

        Parameters

        - vector1 + aggregate
        -

        The first vector to shuffle.

        +

        A value of array or structure type.

        - vector2 + element
        -

        The second vector to shuffle.

        +

        The value to insert.

        - mask + index
        -

        A constant vector of i32 values that acts as a mask -for the shuffled vectors.

        +

        The index at which at which to insert the value.

        +
        + + + + + + name + + + +
        +

        The name for the newly inserted instruction.

        @@ -5845,29 +6939,18 @@

        Parameters

        Return Value

        -

        A value representing a vector with the same element type as the -inputs and length that is the same as the shuffle mask.

        +

        A value representing an aggregate that has been updated with +the given value at the given index.

    • -
    -
    -
    - -
    • @@ -5875,14 +6958,19 @@

      Global Variable Instructions

      -

      Build a named global of the given type.

      +

      Build an instruction to extract a value from a member field in an +aggregate value.

      + +

      An extract value instruction differs from a get element pointer +instruction because the value being indexed is not a pointer and the first +index is unnecessary (as it is assumed to be zero).

      Declaration

      Swift

      -
      public func addGlobal(_ name: String, type: IRType, addressSpace: Int? = nil) -> Global
      +
      public func buildExtractValue(aggregate: IRValue, index: Int, name: String = "") -> IRValue
      @@ -5893,37 +6981,36 @@

      Parameters

      - name + aggregate
      -

      The name of the newly inserted global value.

      +

      A value of array or structure type.

      - type + index
      -

      The type of the newly inserted global value.

      +

      The index at which at which to extract a value.

      - addressSpace + name
      -

      The optional address space where the global -variable resides.

      +

      The name for the newly inserted instruction.

      @@ -5932,17 +7019,31 @@

      Parameters

      Return Value

      -

      A value representing the newly inserted global variable.

      +

      A value representing an aggregate that has been updated with +the given value at the given index.

    + + +
    +
    + + +
    + +

    Vector Instructions

    +

    +
    +
    +
    • @@ -5950,14 +7051,15 @@

      Return Value

      -

      Build a named global of the given type.

      +

      Build a vector insert instruction to nondestructively insert the given +value into the given vector.

      Declaration

      Swift

      -
      public func addGlobal(_ name: String, initializer: IRValue, addressSpace: Int? = nil) -> Global
      +
      public func buildInsertElement(vector: IRValue, element: IRValue, index: IRValue, name: String = "") -> IRValue
      @@ -5968,37 +7070,48 @@

      Parameters

      - name + vector
      -

      The name of the newly inserted global value.

      +

      A value of vector type.

      - initializer + element
      -

      The initial value for the global variable.

      +

      The value to insert.

      - addressSpace + index
      -

      The optional address space where the global -variable resides.

      +

      The index at which to insert the value.

      +
      + + + + + + name + + + +
      +

      The name for the newly inserted instruction.

      @@ -6007,7 +7120,8 @@

      Parameters

      Return Value

      -

      A value representing the newly inserted global variable.

      +

      A value representing a vector that has been updated with +the given value at the given index.

    @@ -6015,9 +7129,9 @@

    Return Value

  • @@ -6025,15 +7139,15 @@

    Return Value

    -

    Build a named global string consisting of an array of i8 type filled in -with the nul terminated string value.

    +

    Build an instruction to extract a single scalar element from a vector at +a specified index.

    Declaration

    Swift

    -
    public func addGlobalString(name: String, value: String) -> Global
    +
    public func buildExtractElement(vector: IRValue, index: IRValue, name: String = "") -> IRValue
    @@ -6044,24 +7158,694 @@

    Parameters

    - name + vector + + + +
    +

    A value of vector type.

    +
    + + + + + + index + + + +
    +

    The index at which to insert the value.

    +
    + + + + + + name + + + +
    +

    The name for the newly inserted instruction.

    +
    + + + + +
    +
    +

    Return Value

    +

    A value representing a scalar at the given index.

    +
    + + +
  • +
  • + +
    +
    +
    +
    +
    +

    Build a vector shuffle instruction to construct a permutation of elements +from the two given input vectors, returning a vector with the same element +type as the inputs and length that is the same as the shuffle mask.

    + +

    The elements of the two input vectors are numbered from left to right +across both of the vectors. The shuffle mask operand specifies, for each +element of the result vector, which element of the two input vectors the +result element gets. If the shuffle mask is undef, the result vector is +also undef. If any element of the mask operand is undef, that element +of the result is undef. If the shuffle mask selects an undef element +from one of the input vectors, the resulting element is undef.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func buildShuffleVector(_ vector1: IRValue, and vector2: IRValue, mask: IRValue, name: String = "") -> IRValue
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + vector1 + + +
    +

    The first vector to shuffle.

    +
    +
    + + vector2 + + +
    +

    The second vector to shuffle.

    +
    +
    + + mask + + +
    +

    A constant vector of i32 values that acts as a mask +for the shuffled vectors.

    +
    +
    +
    +
    +

    Return Value

    +

    A value representing a vector with the same element type as the +inputs and length that is the same as the shuffle mask.

    +
    +
    +
    +
  • + + +
    +
    + + +
    + +

    Global Variable Instructions

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Build a named global of the given type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func addGlobal(_ name: String, type: IRType, addressSpace: AddressSpace = .zero) -> Global
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + name + + +
      +

      The name of the newly inserted global value.

      +
      +
      + + type + + +
      +

      The type of the newly inserted global value.

      +
      +
      + + addressSpace + + +
      +

      The optional address space where the global +variable resides.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing the newly inserted global variable.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Build a named global of the given type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func addGlobal(_ name: String, initializer: IRValue, addressSpace: AddressSpace = .zero) -> Global
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + name + + +
      +

      The name of the newly inserted global value.

      +
      +
      + + initializer + + +
      +

      The initial value for the global variable.

      +
      +
      + + addressSpace + + +
      +

      The optional address space where the global +variable resides.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing the newly inserted global variable.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Build a named global string consisting of an array of i8 type filled in +with the nul terminated string value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func addGlobalString(name: String, value: String) -> Global
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + name + + +
      +

      The name of the newly inserted global string value.

      +
      +
      + + value + + +
      +

      The character contents of the newly inserted global.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing the newly inserted global string variable.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Build a named global variable containing the characters of the given +string value as an array of i8 type filled in with the nul terminated +string value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildGlobalString(_ string: String, name: String = "") -> Global
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + string + + +
      +

      The character contents of the newly inserted global.

      +
      +
      + + name + + +
      +

      The name for the newly inserted instruction.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing the newly inserted global string variable.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Build a named global variable containing a pointer to the contents of the +given string value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildGlobalStringPtr(_ string: String, name: String = "") -> IRValue
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + string + + +
      +

      The character contents of the newly inserted global.

      +
      +
      + + name + + +
      +

      The name for the newly inserted instruction.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing a pointer to the newly inserted global +string variable.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Build a named alias to a global value or a constant expression.

      + +

      Aliases, unlike function or variables, don’t create any new data. They are +just a new symbol and metadata for an existing position.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func addAlias(name: String, to aliasee: IRGlobal, type: IRType) -> Alias
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + name + + +
      +

      The name of the newly inserted alias.

      +
      +
      + + aliasee + + +
      +

      The value or constant to alias.

      +
      +
      + + type + + +
      +

      The type of the aliased value or expression.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing the newly created alias.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Inline Assembly

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Build a value representing an inline assembly expression (as opposed to +module-level inline assembly).

      + +

      LLVM represents inline assembler as a template string (containing the +instructions to emit), a list of operand constraints (stored as a string), +and some flags.

      + +

      The template string supports argument substitution of the operands using +“$” followed by a number, to indicate substitution of the given +register/memory location, as specified by the constraint string. +“${NUM:MODIFIER}” may also be used, where MODIFIER is a target-specific +annotation for how to print the operand (see Asm Template Argument +Modifiers).

      + +

      LLVM’s support for inline asm is modeled closely on the requirements of +Clang’s GCC-compatible inline-asm support. Thus, the feature-set and the +constraint and modifier codes are similar or identical to those in GCC’s +inline asm support.

      + +

      However, the syntax of the template and constraint strings is not the +same as the syntax accepted by GCC and Clang, and, while most constraint +letters are passed through as-is by Clang, some get translated to other +codes when converting from the C source to the LLVM assembly.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildInlineAssembly(
      +  _ asm: String, dialect: InlineAssemblyDialect, type: FunctionType,
      +  constraints: String = "",
      +  hasSideEffects: Bool = true, needsAlignedStack: Bool = true
      +) -> IRValue
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + @@ -6070,17 +7854,31 @@

      Parameters

      Return Value

      -

      A value representing the newly inserted global string variable.

      +

      A representation of the newly created inline assembly +expression.

      + + +
      +
      + + +
      + +

      Deprecated APIs

      +

      +
      +
      +
      • @@ -6088,16 +7886,19 @@

        Return Value

        -

        Builds a named global variable containing the characters of the given -string value as an array of i8 type filled in with the nul terminated -string value.

        +

        Build a load instruction that loads a value from the location in the +given value.

        + +

        If alignment is not specified, or if zero, the target will choose a default +value that is convenient and compatible with the type.

        Declaration

        Swift

        -
        public func buildGlobalString(_ string: String, name: String = "") -> Global
        +
        @available(*, deprecated, message: "Use buildLoad(_:type:ordering:volatile:alignment:name﹚ instead")
        +public func buildLoad(_ ptr: IRValue, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false, alignment: Alignment = .zero, name: String = "") -> IRInstruction
        @@ -6108,12 +7909,49 @@

        Parameters

      + + + + + + + + + + + + @@ -6134,7 +7972,8 @@

      Parameters

      Return Value

      -

      A value representing the newly inserted global string variable.

      +

      A value representing the result of a load from the given +pointer value.

      @@ -6142,9 +7981,9 @@

      Return Value

    • @@ -6152,15 +7991,16 @@

      Return Value

      -

      Builds a named global variable containing a pointer to the contents of the -given string value.

      +

      Build a GEP (Get Element Pointer) instruction suitable for indexing into +a struct.

      Declaration

      Swift

      -
      public func buildGlobalStringPtr(_ string: String, name: String = "") -> IRValue
      +
      @available(*, deprecated, message: "Use buildStructGEP(_:type:index:name﹚ instead")
      +public func buildStructGEP(_ ptr: IRValue, index: Int, name: String = "") -> IRValue
      @@ -6171,12 +8011,24 @@

      Parameters

    • + + + + @@ -6197,8 +8049,8 @@

      Parameters

      Return Value

      -

      A value representing a pointer to the newly inserted global -string variable.

      +

      A value representing the address of a subelement of the given +struct value.

      @@ -6206,9 +8058,9 @@

      Return Value

    • @@ -6216,17 +8068,19 @@

      Return Value

      -

      Builds a named alias to a global value or a constant expression.

      +

      Build a GEP (Get Element Pointer) instruction.

      -

      Aliases, unlike function or variables, don’t create any new data. They are -just a new symbol and metadata for an existing position.

      +

      The GEP instruction is often the source of confusion. LLVM provides a +document to answer questions +around its semantics and correct usage.

      Declaration

      Swift

      -
      public func addAlias(name: String, to aliasee: IRGlobal, type: IRType) -> Alias
      +
      @available(*, deprecated, message: "Use buildGEP(_:type:indices:name﹚ instead")
      +public func buildGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue
      @@ -6234,6 +8088,31 @@

      Declaration

      Parameters

    • + + asm
      -

      The name of the newly inserted global string value.

      +

      The inline assembly expression template string.

      - value + type
      -

      The character contents of the newly inserted global.

      +

      The type of the parameters and return value of the +assembly expression string.

      +
      +
      + + constraints + + +
      +

      A comma-separated string, each element containing +one or more constraint codes.

      +
      +
      + + hasSideEffects + + +
      +

      Whether this inline asm expression has +side effects. Defaults to false.

      +
      +
      + + needsAlignedStack + + +
      +

      Whether the function containing the +asm needs to align its stack conservatively. Defaults to true.

      - string + ptr
      -

      The character contents of the newly inserted global.

      +

      The pointer value to load from.

      +
      +
      + + ordering + + +
      +

      The ordering effect of the fence for this load, +if any. Defaults to a nonatomic load.

      +
      +
      + + volatile + + +
      +

      Whether this is a load from a volatile memory location.

      +
      +
      + + alignment + + +
      +

      The alignment of the access.

      - string + ptr
      -

      The character contents of the newly inserted global.

      +

      The base address for the index calculation.

      +
      +
      + + index + + +
      +

      The offset from the base for the index calculation.

      + + + + + + + + + + +
      + + ptr + + +
      +

      The base address for the index calculation.

      +
      +
      + + indices + + +
      +

      A list of indices that indicate which of the elements +of the aggregate object are indexed.

      +
      +
      @@ -6242,31 +8121,90 @@

      Parameters

      -

      The name of the newly inserted alias.

      +

      The name for the newly inserted instruction.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing the address of a subelement of the given +aggregate data structure value.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Build a GEP (Get Element Pointer) instruction with a resultant value +that is undefined if the address is outside the actual underlying +allocated object and not the address one-past-the-end.

      + +

      The GEP instruction is often the source of confusion. LLVM provides a +document to answer questions +around its semantics and correct usage.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      @available(*, deprecated, message: "Use buildInBoundsGEP(_:type:indices:name﹚ instead")
      +public func buildInBoundsGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue
      + +
      +
      +
      +

      Parameters

      + + + + + @@ -6275,7 +8213,8 @@

      Parameters

      Return Value

      -

      A value representing the newly created alias.

      +

      A value representing the address of a subelement of the given +aggregate data structure value.

      @@ -6285,8 +8224,8 @@

      Return Value

      diff --git a/docs/Classes/Intrinsic.html b/docs/Classes/Intrinsic.html new file mode 100644 index 00000000..4997f7aa --- /dev/null +++ b/docs/Classes/Intrinsic.html @@ -0,0 +1,947 @@ + + + + Intrinsic Class Reference + + + + + + + + + + + + + +
      +
      +

      LLVM 0.8 Docs (100% documented)

      +

      +
      + + +

      +
      +
      +
      + +
      +
      + +
      +
      +
      +

      Intrinsic

      +
      +
      + +
      public class Intrinsic : Function
      + +
      +
      +

      An Intrinsic represents an intrinsic known to LLVM.

      + +

      Intrinsic functions have well known names and semantics and are required to +follow certain restrictions. Overall, these intrinsics represent an +extension mechanism for the LLVM language that does not require changing all +of the transformations in LLVM when adding to the language (or the bitcode +reader/writer, the parser, etc…).

      + +

      Intrinsic function names must all start with an llvm. prefix. This prefix +is reserved in LLVM for intrinsic names; thus, function names may not begin +with this prefix. Intrinsic functions must always be external functions: you +cannot define the body of intrinsic functions. Intrinsic functions may only +be used in call or invoke instructions: it is illegal to take the address of +an intrinsic function.

      + +

      Some intrinsic functions can be overloaded, i.e., the intrinsic represents a +family of functions that perform the same operation but on different data +types. Because LLVM can represent over 8 million different integer types, +overloading is used commonly to allow an intrinsic function to operate on +any integer type. One or more of the argument types or the result type can +be overloaded to accept any integer type. Argument types may also be defined +as exactly matching a previous argument’s type or the result type. This +allows an intrinsic function which accepts multiple arguments, but needs all +of them to be of the same type, to only be overloaded with respect to a +single argument or the result.

      + +

      Overloaded intrinsics will have the names of its overloaded argument types +encoded into its function name, each preceded by a period. Only those types +which are overloaded result in a name suffix. Arguments whose type is +matched against another type do not. For example, the llvm.ctpop function +can take an integer of any width and returns an integer of exactly the same +integer width. This leads to a family of functions such as +i8 @llvm.ctpop.i8(i8 %val) and i29 @llvm.ctpop.i29(i29 %val). Only one +type, the return type, is overloaded, and only one type suffix is required. +Because the argument’s type is matched against the return type, it does not +require its own name suffix.

      +

      Dynamic Member Lookup For Intrinsics

      + +

      This library provides a dynamic member lookup facility for retrieving +intrinsic selectors. For any LLVM intrinsic selector of the form +llvm.foo.bar.baz, the name of the corresponding dynamic member is that +name with any dots replaced by underscores.

      + +

      For example:

      +
      llvm.foo.bar.baz -> Intrinsic.ID.llvm_foo_bar_baz
      +llvm.stacksave -> Intrinsic.ID.llvm_stacksave
      +llvm.x86.xsave64 -> Intrinsic.ID.llvm_x86_xsave64
      +
      + +

      Any existing underscores do not need to be replaced, e.g. +llvm.va_copy becomes Intrinsic.ID.llvm_va_copy.

      + +

      For overloaded intrinsics, the non-overloaded prefix excluding the explicit +type parameters is used and normalized according to the convention above.

      + +

      For example:

      +
      llvm.sinf64 -> Intrinsic.ID.llvm_sin
      +llvm.memcpy.p0i8.p0i8.i32 -> Intrinsic.ID.llvm_memcpy
      +llvm.bswap.v4i32 -> Intrinsic.ID.llvm_bswap
      +
      + +
      +
      +
      +
        +
      • +
        + + + + Selector + +
        +
        +
        +
        +
        +
        +

        A wrapper type for an intrinsic selector.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        public struct Selector
        + +
        +
        +
        +
        +
      • +
      • + +
        +
        +
        +
        +
        +

        This type provides a dynamic member lookup facility for LLVM intrinsics.

        + +

        It is not possible to create a DynamicIntrinsicResolver in user code. +One is provided by Intrinsic.ID.

        + + See more +
        +
        +

        Declaration

        +
        +

        Swift

        +
        @dynamicMemberLookup
        +public struct DynamicIntrinsicResolver
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + ID + +
        +
        +
        +
        +
        +
        +

        The default dynamic intrinsic resolver.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        public static let ID: Intrinsic.DynamicIntrinsicResolver
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + name + +
        +
        +
        +
        +
        +
        +

        Retrieves the name of this intrinsic if it is not overloaded.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        public var name: String { get }
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + overloadedName(for:) + +
        +
        +
        +
        +
        +
        +

        Retrieves the name of this intrinsic if it is overloaded, resolving it +with the given parameter types.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        public func overloadedName(for parameterTypes: [IRType]) -> String
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + type + +
        +
        +
        +
        +
        +
        +

        Retrieves the type of this intrinsic if it is not overloaded.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        public var type: IRType { get }
        + +
        +
        +
        +
        +
      • +
      • + +
        +
        +
        +
        +
        +

        Resolves the type of an overloaded intrinsic using the given parameter +types.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        public func overloadedType(in context: Context = .global, with parameterTypes: [IRType]) -> IRType
        + +
        +
        +
        +

        Parameters

        +
      + + ptr + + +
      +

      The base address for the index calculation.

      - aliasee + indices
      -

      The value or constant to alias.

      +

      A list of indices that indicate which of the elements +of the aggregate object are indexed.

      - type + name
      -

      The type of the aliased value or expression.

      +

      The name for the newly inserted instruction.

      + + + + + + + + + + +
      + + context + + +
      +

      The context in which to create the type.

      +
      +
      + + parameterTypes + + +
      +

      The type of the parameters to the intrinsic.

      +
      +
      +
      +
      +

      Return Value

      +

      The type of the intrinsic function with its overloaded +parameter types resolved.

      +
      +
      +
      +
    • +
    • +
      + + + + isOverloaded + +
      +
      +
      +
      +
      +
      +

      Retrieves if this intrinsic is overloaded.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var isOverloaded: Bool { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + identifier + +
      +
      +
      +
      +
      +
      +

      Retrieves the ID number of this intrinsic function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var identifier: UInt32 { get }
      + +
      +
      +
      +
      +
    • +
    +
    + + + + + + + + diff --git a/docs/Classes/Intrinsic/DynamicIntrinsicResolver.html b/docs/Classes/Intrinsic/DynamicIntrinsicResolver.html new file mode 100644 index 00000000..b6be90d1 --- /dev/null +++ b/docs/Classes/Intrinsic/DynamicIntrinsicResolver.html @@ -0,0 +1,676 @@ + + + + DynamicIntrinsicResolver Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    DynamicIntrinsicResolver

    +
    +
    + +
    @dynamicMemberLookup
    +public struct DynamicIntrinsicResolver
    + +
    +
    +

    This type provides a dynamic member lookup facility for LLVM intrinsics.

    + +

    It is not possible to create a DynamicIntrinsicResolver in user code. +One is provided by Intrinsic.ID.

    + +
    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Performs a dynamic lookup for the normalized form of an intrinsic +selector.

      + +

      For any LLVM intrinsic selector of the form llvm.foo.bar.baz, the name +of the corresponding dynamic member is that name with any dots replaced +by underscores.

      + +

      For example:

      +
      llvm.foo.bar.baz -> Intrinsic.ID.llvm_foo_bar_baz
      +llvm.stacksave -> Intrinsic.ID.llvm_stacksave
      +llvm.x86.xsave64 -> Intrinsic.ID.llvm_x86_xsave64
      +
      + +

      Any existing underscores do not need to be replaced, e.g. +llvm.va_copy becomes Intrinsic.ID.llvm_va_copy.

      + +

      For overloaded intrinsics, the non-overloaded prefix excluding the +explicit type parameters is used and normalized according to the +convention above.

      + +

      For example:

      +
      llvm.sinf64 -> Intrinsic.ID.llvm_sin
      +llvm.memcpy.p0i8.p0i8.i32 -> Intrinsic.ID.llvm_memcpy
      +llvm.bswap.v4i32 -> Intrinsic.ID.llvm_bswap
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public subscript(dynamicMember selector: String) -> Selector { get }
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + selector + + +
      +

      The LLVMSwift form of an intrinsic selector.

      +
      +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/JIT.html b/docs/Classes/JIT.html index debb6aa0..eab488c9 100644 --- a/docs/Classes/JIT.html +++ b/docs/Classes/JIT.html @@ -8,18 +8,26 @@ + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    + +
  • +
    + + + + address(of:in:) + +
    +
    +
    +
    +
    +
    +

    Computes the address of the given symbol, optionally restricting the +search for its address to a particular module. If this symbol does not +exist, an address of 0 is returned.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func address(of symbol: String, in module: ModuleHandle? = nil) throws -> TargetAddress
    + +
    +
    +
    +

    Parameters

    + + + + + + + +
    + + symbol + + +
    +

    The symbol name to search for.

    +
    +
    @@ -391,34 +790,113 @@

    Parameters

    -

    The module containing code you wish to execute

    +

    An optional value describing the module in which to +restrict the search, if any.

    +
    +
    +

    Return Value

    +

    The address of the symbol, or 0 if it does not exist.

    +
    +
    +
    +
  • + + +
    +
    + + +
    + +

    Lazy Compilation

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Registers a lazy compile callback that can be used to get the target +address of a trampoline function. When that trampoline address is +called, the given compilation callback is fired.

      + +

      Normally, the trampoline function is a known stub that has been previously +registered with the JIT. The callback then computes the address of a +known entry point and sets the address of the stub to it. See +JIT.createIndirectStub to create a stub function and +JIT.setIndirectStubPointer to set the address of a stub.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func registerLazyCompile(_ callback: @escaping (JIT) -> TargetAddress) throws -> TargetAddress
      + +
      +
      +
      +

      Parameters

      + +
      - machine + callback
      -

      The target machine which you’re compiling for

      +

      A callback that returns the actual address of the +trampoline function.

      +
      +

      Return Value

      +

      The target address representing a stub. Calling this stub +forces the given compilation callback to fire.

      +
    • +
    +
    +
    +
    + + +
    + +

    Stubs

    +

    +
    +
    +
    • @@ -426,16 +904,17 @@

      Parameters

      -

      Runs the specified function with the provided arguments by compiling -it to machine code for the target architecture used to initialize this -JIT.

      +

      Creates a new named indirect stub pointing to the given target address.

      + +

      An indirect stub may be resolved to a different address at any time by +invoking JIT.setIndirectStubPointer.

      Declaration

      Swift

      -
      public func runFunction(_ function: Function, args: [IRValue]) -> IRValue
      +
      public func createIndirectStub(named name: String, address: TargetAddress) throws
      @@ -446,43 +925,39 @@

      Parameters

      - function + name
      -

      The function you wish to execute

      +

      The name of the indirect stub.

      - args + address
      -

      The arguments you wish to pass to the function

      +

      The address of the indirect stub.

      -
      -

      Return Value

      -

      The LLVM value that the function returned

      -
  • @@ -490,25 +965,21 @@

    Return Value

    -

    Retrieves a pointer to the function compiled by this JIT.

    -
    -

    Note

    - You will have to unsafeBitCast this pointer to - the appropriate @convention(c) function type to be - able to run it from Swift. +

    Resets the address of an indirect stub.

    +
    +

    Warning

    +

    The indirect stub must be registered with a call to +JIT.createIndirectStub. Failure to do so will result in undefined +behavior.

    -
    typealias FnPtr = @convention(c) () -> Double
    -let fnAddr = jit.addressOfFunction(name: "test")
    -let fn = unsafeBitCast(fnAddr, to: FnPtr.self)
    -

    Declaration

    Swift

    -
    public func addressOfFunction(name: String) -> OpaquePointer?
    +
    public func setIndirectStubPointer(named name: String, address: TargetAddress) throws
    @@ -524,26 +995,47 @@

    Parameters

    -

    The name of the function you wish to look up.

    +

    The name of an indirect stub.

    +
    + + + + + + address + + + +
    +

    The address to set the indirect stub to point to.

    -
    -

    Return Value

    -

    A pointer to the result of compiling the specified function.

    -
  • + + +
    +
    + + +
    + +

    Adding Code to the JIT

    +

    +
    +
    +
    • @@ -551,14 +1043,31 @@

      Return Value

      -

      Adds the provided module, and all top-level declarations into this JIT.

      +

      Adds the IR from a given module to the JIT, consuming it in the process.

      + +

      Despite the name of this function, the callback to compile the symbols in +the module is not necessarily called immediately. It is called at least +when a given symbol’s address is requested, either by the JIT or by +the user e.g. JIT.address(of:).

      + +

      The callback function is required to compute the address of the given +symbol. The symbols are passed in mangled form. Use +JIT.mangle(symbol:) to request the mangled name of a symbol.

      +
      +

      Warning

      +

      The JIT invalidates the underlying reference to the provided +module. Further references to the module are thus dangling pointers and +may be a source of subtle memory bugs. This will be addressed in a +future revision of LLVM.

      + +

      Declaration

      Swift

      -
      public func addModule(_ module: Module)
      +
      public func addEagerlyCompiledIR(_ module: Module, _ callback: @escaping (String) -> TargetAddress) throws -> ModuleHandle
      @@ -574,7 +1083,20 @@

      Parameters

      -

      The module you wish to add.

      +

      The module to compile.

      +
      + + + + + + callback + + + +
      +

      A function that is called by the JIT to compute the +address of symbols.

      @@ -587,9 +1109,9 @@

      Parameters

    • @@ -597,27 +1119,74 @@

      Parameters

      -

      Removes the provided module, and all top-level declarations, from this -JIT.

      +

      Adds the IR from a given module to the JIT, consuming it in the process.

      + +

      This function differs from JIT.addEagerlyCompiledIR in that the callback +to request the address of symbols is only executed when that symbol is +called, either in user code or by the JIT.

      + +

      The callback function is required to compute the address of the given +symbol. The symbols are passed in mangled form. Use +JIT.mangle(symbol:) to request the mangled name of a symbol.

      +
      +

      Warning

      +

      The JIT invalidates the underlying reference to the provided +module. Further references to the module are thus dangling pointers and +may be a source of subtle memory bugs. This will be addressed in a +future revision of LLVM.

      + +

      Declaration

      Swift

      -
      public func removeModule(_ module: Module) throws
      +
      public func addLazilyCompiledIR(_ module: Module, _ callback: @escaping (String) -> TargetAddress) throws -> ModuleHandle
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + module + + +
      +

      The module to compile.

      +
      +
      + + callback + + +
      +

      A function that is called by the JIT to compute the +address of symbols.

      +
      +
      +
    • @@ -625,16 +1194,27 @@

      Declaration

      -

      Runs the specified function as if it were the main function in an -executable. It takes an array of argument strings and passes them -into the function as argc and argv.

      +

      Adds the executable code from an object file to ths JIT, consuming it in +the process.

      + +

      The callback function is required to compute the address of the given +symbol. The symbols are passed in mangled form. Use +JIT.mangle(symbol:) to request the mangled name of a symbol.

      +
      +

      Warning

      +

      The JIT invalidates the underlying reference to the provided +memory buffer. Further references to the buffer are thus dangling +pointers and may be a source of subtle memory bugs. This will be +addressed in a future revision of LLVM.

      + +

      Declaration

      Swift

      -
      public func runFunctionAsMain(_ function: Function, args: [String]) -> Int
      +
      public func addObjectFile(_ buffer: MemoryBuffer, _ callback: @escaping (String) -> TargetAddress) throws -> ModuleHandle
      @@ -645,33 +1225,82 @@

      Parameters

      - function + buffer
      -

      The main function you wish to execute

      +

      A buffer containing an object file.

      - args + callback
      -

      The string arguments you wish to pass to the function

      +

      A function that is called by the JIT to compute the +address of symbols.

      +
    • +
      +
    • +
    • +
      + + + + removeModule(_:) + +
      +
      +
      +
      +
      +
      +

      Remove previously-added code from the JIT.

      +
      +

      Warning

      +

      Removing a module handle consumes the handle. Further use of +the handle will then result in undefined behavior.

      + +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func removeModule(_ handle: ModuleHandle) throws
      + +
      +
      -

      Return Value

      -

      The numerical exit code returned by the function

      +

      Parameters

      + + + + + + + +
      + + handle + + +
      +

      A handle to previously-added module.

      +
      +
      @@ -681,8 +1310,8 @@

      Return Value

    diff --git a/docs/Classes/JIT/TargetAddress.html b/docs/Classes/JIT/TargetAddress.html new file mode 100644 index 00000000..fd5f5dde --- /dev/null +++ b/docs/Classes/JIT/TargetAddress.html @@ -0,0 +1,709 @@ + + + + TargetAddress Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    TargetAddress

    +
    +
    + +
    public struct TargetAddress : Comparable
    + +
    +
    +

    A type that represents an address, either symbolically within the JIT or +physically in the execution environment.

    + +
    +
    +
    +
      +
    • +
      + + + + init() + +
      +
      +
      +
      +
      +
      +

      Creates a target address value of 0.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init()
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(raw:) + +
      +
      +
      +
      +
      +
      +

      Creates a target address from a raw address value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(raw: LLVMOrcTargetAddress)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ==(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func == (lhs: TargetAddress, rhs: TargetAddress) -> Bool
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + <(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func < (lhs: TargetAddress, rhs: TargetAddress) -> Bool
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/MDBuilder.html b/docs/Classes/MDBuilder.html new file mode 100644 index 00000000..4eb4da74 --- /dev/null +++ b/docs/Classes/MDBuilder.html @@ -0,0 +1,1772 @@ + + + + MDBuilder Class Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    MDBuilder

    +
    +
    + +
    public final class MDBuilder
    + +
    +
    +

    An MDBuilder object provides a convenient way to build common metadata +nodes.

    + +
    +
    +
    +
      +
    • +
      + + + + context + +
      +
      +
      +
      +
      +
      +

      The context used to intialize this metadata builder.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public let context: Context
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(in:) + +
      +
      +
      +
      +
      +
      +

      Creates a metadata builder with the given context.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(in context: Context = .global)
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + context + + +
      +

      The context in which to create metadata.

      +
      +
      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Floating Point Accuracy Metadata

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Builds metadata describing the accuracy of a floating-point computation +using the given accuracy value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildFloatingPointMathTag(_ accuracy: Float) -> MDNode?
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + accuracy + + +
      +

      The accuracy value.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node describing the accuracy of a floating-point +computation.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Branch Prediction Metadata

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Builds branch weight metadata for a set of branch targets of a branch, +select, switch, or call instruction.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildBranchWeights(_ weights: [Int]) -> MDNode
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + weights + + +
      +

      The weights of the branches.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node containing the given branch-weight information.

      +
      +
      +
      +
    • +
    • +
      + + + + buildUnpredictable() + +
      +
      +
      +
      +
      +
      +

      Builds branch metadata that expresses that the flow of control is +unpredictable in a given branch or switch instruction.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildUnpredictable() -> MDNode
      + +
      +
      +
      +

      Return Value

      +

      A metadata node representing unpredictable branch metadata.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Section Prefix Metadata

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Builds section prefix metadata.

      + +

      LLVM allows an explicit section to be specified for functions. If the +target supports it, it will emit functions to the section specified. +Additionally, the function can be placed in a COMDAT.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildFunctionSectionPrefix(_ section: String) -> MDNode
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + section + + +
      +

      The section into which functions annotated with this +metadata should be emitted.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node representing the section prefix metadata.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Range Metadata

    +

    +
    +
    +
      +
    • +
      + + + + buildRange(_:_:) + +
      +
      +
      +
      +
      +
      +

      Builds range metadata.

      + +

      Range metadata may be attached only to load, call and invoke of integer +types. It expresses the possible ranges the loaded value or the value +returned by the called function at this call site is in. If the loaded +or returned value is not in the specified range, the behavior is +undefined.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildRange(_ lo: APInt, _ hi: APInt) -> MDNode?
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lo + + +
      +

      The lower bound on the range.

      +
      +
      + + hi + + +
      +

      The upper bound on the range.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node representing the newly created range metadata.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Callee Metadata

    +

    +
    +
    +
      +
    • +
      + + + + buildCallees(_:) + +
      +
      +
      +
      +
      +
      +

      Build callees metadata.

      + +

      Callees metadata may be attached to indirect call sites. If callees +metadata is attached to a call site, and any callee is not among the +set of functions provided by the metadata, the behavior is undefined.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildCallees(_ callees: [Function]) -> MDNode
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + callees + + +
      +

      An array of callee function values.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node representing the newly created callees metadata.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Callback Metadata

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Build Callback metadata.

      + +

      Callback metadata may be attached to a function declaration, or +definition. The metadata describes how the arguments of a call to a +function are in turn passed to the callback function specified by the +metadata. Thus, the callback metadata provides a partial description of +a call site inside the function with regards to the arguments of a call +to the function. The only semantic restriction on the function itself is +that it is not allowed to inspect or modify arguments referenced in the +callback metadata as pass-through to the callback function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildCallbackEncoding(
      +  _ callbackIndex: UInt, _ argumentIndices: [Int],
      +  passVariadicArguments: Bool = false
      +) -> MDNode
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + callbackIndex + + +
      +

      The argument index of the callback.

      +
      +
      + + argumentIndices + + +
      +

      An array of argument indices in the caller that +are passed to the callback function.

      +
      +
      + + passVariadicArguments + + +
      +

      If true, denotes that all variadic arguments +of the function are passed to the callback.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node representing the newly created callees metadata.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Function Entry Count Metadata

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Build function entry count metadata.

      + +

      Function entry count metadata can be attached to function definitions to +record the number of times the function is called. Used with +block frequency information, it is also used to derive the basic block +profile count.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildFunctionEntryCount(
      +  _ count: UInt, imports: Set<UInt64> = [], synthetic: Bool = false
      +) -> MDNode
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + count + + +
      +

      The number of times a function is called.

      +
      +
      + + imports + + +
      +

      The GUID of global values that should be imported along with +this function when running PGO.

      +
      +
      + + synthetic + + +
      +

      Whether the entry count is synthetic. User-created +metadata should not be synthetic outside of PGO passes.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node representing the newly created entry count metadata.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    TBAA Metadata

    +

    +
    +
    +
      +
    • +
      + + + + buildTBAARoot(_:) + +
      +
      +
      +
      +
      +
      +

      Build a metadata node for the root of a TBAA hierarchy with the given +name.

      + +

      The root node of a TBAA hierarchy describes a boundary for a source +language’s type system. For the purposes of optimization, a TBAA analysis +pass must consider ancestors of two different root systems mayalias.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildTBAARoot(_ name: String = "") -> MDNode
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + name + + +
      +

      The name of the TBAA root node.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node representing a TBAA hierarchy root.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Build a metadata node suitable for an alias.scope metadata attachment.

      + +

      When evaluating an aliasing query, if for some domain, the set of scopes +with that domain in one instruction’s alias.scope list is a subset of (or +equal to) the set of scopes for that domain in another instruction’s +noalias list, then the two memory accesses are assumed not to alias.

      + +

      Because scopes in one domain don’t affect scopes in other domains, +separate domains can be used to compose multiple independent noalias +sets. This is used for example during inlining. As the noalias function +parameters are turned into noalias scope metadata, a new domain is used +every time the function is inlined.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildAliasScopeDomain(_ name: String = "", _ domain: MDNode? = nil) -> MDNode
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + name + + +
      +

      The name of the alias scope domain.

      +
      +
      + + domain + + +
      +

      The domain of the alias scope, if any.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node representing a TBAA alias scope.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Builds a metadata node suitable for a tbaa.struct metadata attachment.

      + +

      tbaa.struct metadata can describe which memory subregions in a +memcpy are padding and what the TBAA tags of the struct are.

      + +

      Note that the fields need not be contiguous. In the following example, +there is a 4 byte gap between the two fields. This gap represents padding +which does not carry useful data and need not be preserved.

      +
      !4 = !{ i64 0, i64 4, !1, i64 8, i64 4, !2 }
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildTBAAStructNode(_ fields: [TBAAStructField]) -> MDNode
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + fields + + +
      +

      The fields of the struct.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node representing a TBAA struct descriptor.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Builds a TBAA Type Descriptor.

      + +

      Type descriptors describe the type system of the higher level language +being compiled and come in two variants:

      +

      Scalar Type Descriptors

      + +

      Scalar type descriptors describe types that do not contain other types, +such as fixed-width integral and floating-point types. A scalar type +has a single parent, which is required to be another scalar type or +the TBAA root node. For example, in C, int32_t would be described be +a scalar type node with a parent pointer to unsigned char which, in +turn, points to the root for C.

      +
      +----------+   +------+   +-----------+
      +|          |   |      |   |           |
      +| uint32_t +---> char +---> TBAA Root |
      +|          |   |      |   |           |
      ++----------+   +------+   +-----------+
      +
      +

      Struct Type Descriptors

      + +

      Struct type descriptors describe types that contain a sequence of other +type descriptors, at known offsets, as fields. These field type +descriptors can either be struct type descriptors themselves or scalar +type descriptors.

      +
                    +----------+
      +              |          |
      +      +-------> uint32_t +----+
      +      |       |          |    |
      +      |       +----------+    |
      ++------------+            +---v--+   +-----------+
      +|            |            |      |   |           |
      +| SomeStruct |            | char +---> TBAA Root |
      +|            |            |      |   |           |
      ++------------+            +---^--+   +-----------+
      +      |          +-------+    |
      +      |          |       |    |
      +      +----------> float +----+
      +                 |       |
      +                 +-------+
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildTBAATypeNode(
      +  _ id: IRMetadata, parent: MDNode, size: Size, fields: [TBAAStructField] = []
      +) -> MDNode
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + +
      + + parent + + +
      +

      The parent type node of this type node or the TBAA root node +if it is a top-level entity.

      +
      +
      + + size + + +
      +

      The size of the type in bytes.

      +
      +
      + + id + + +
      +

      The metadata node whose identity uniquely identifies this node as +well. These are often MDString values.

      +
      +
      + + fields + + +
      +

      The fields of the type, if any.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node representing a TBAA type descriptor.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Builds a TBAA Access Tag.

      + +

      Access tags are metadata nodes attached to load and store +instructions. Access tags use type descriptors to describe the +location being accessed in terms of the type system of the higher +level language. Access tags are tuples consisting of a base type, +an access type and an offset. The base type is a scalar type +descriptor or a struct type descriptor, the access type is a +scalar type descriptor, and the offset is a constant integer.

      +

      Tag Structure

      + +

      The access tag (BaseTy, AccessTy, Offset) can describe one of two +things:

      + +
        +
      • If BaseTy is a struct type, the tag describes a memory access +(load or store) of a value of type AccessTy contained in +the struct type BaseTy at offset Offset.
      • +
      • If BaseTy is a scalar type, Offset must be 0 and BaseTy and +AccessTy must be the same; and the access tag describes a scalar +access with scalar type AccessTy.

      • +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildTBAAAccessTag(
      +  baseType: MDNode, accessType: MDNode,
      +  offset: Size, size: Size, immutable: Bool = false
      +) -> MDNode
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + + + + + + + + + +
      + + baseType + + +
      +

      The base type of the access. This is the structure or +scalar type that corresponds to the type of the source value in a +load instruction, or the type of the destination value in a store +instruction.

      +
      +
      + + accessType + + +
      +

      The type of the accessed value. This is the type that +corresponds to the type of the destination value in a load +instruction, or the type of the source value in a store instruction.

      +
      +
      + + offset + + +
      +

      The ofset of the memory access into the base type. If the +base type is scalar, this value must be 0.

      +
      +
      + + size + + +
      +

      The size of the access in bytes.

      +
      +
      + + immutable + + +
      +

      If true, accesses to this memory are never writes. +This corresponds to the const memory qualifier in C and C++.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node representing a TBAA access tag.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Irreducible Loop Metadata

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Builds irreducible loop metadata.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func buildIrreducibleLoopHeaderWeight(_ weight: UInt) -> MDNode
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + weight + + +
      +

      The weight of a loop header.

      +
      +
      +
      +
      +

      Return Value

      +

      A metadata node representing the newly created +irreducible loop metadata.

      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/MachOUniversalBinaryFile.html b/docs/Classes/MachOUniversalBinaryFile.html new file mode 100644 index 00000000..0a790645 --- /dev/null +++ b/docs/Classes/MachOUniversalBinaryFile.html @@ -0,0 +1,803 @@ + + + + MachOUniversalBinaryFile Class Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    MachOUniversalBinaryFile

    +
    +
    + +
    public final class MachOUniversalBinaryFile : BinaryFile
    + +
    +
    +

    An in-memory representation of a Mach-O universal binary file.

    + +
    +
    +
    +
      +
    • +
      + + + + init(path:) + +
      +
      +
      +
      +
      +
      +

      Creates an MachOUniversalBinaryFile with the contents of the object file at +the provided path.

      +
      +

      Throws

      + MemoryBufferError or BinaryFileError if there was an error + on creation + +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public convenience init(path: String) throws
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + path + + +
      +

      The absolute file path on your filesystem.

      +
      +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Creates a Mach-O universal binary file with the contents of a provided +memory buffer.

      +
      +

      Throws

      + BinaryFileError if there was an error on creation. + +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public override init(memoryBuffer: MemoryBuffer, in context: Context = .global) throws
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + memoryBuffer + + +
      +

      A memory buffer containing a valid universal Mach-O file.

      +
      +
      + + context + + +
      +

      The context to allocate the given binary in.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + objectFile(for:) + +
      +
      +
      +
      +
      +
      +

      Retrieves the object file for a specific architecture, if it exists.

      +
      +

      Throws

      + BinaryFileError if there was an error on creation. + +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func objectFile(for architecture: Triple.Architecture) throws -> Slice
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + architecture + + +
      +

      The architecture of a Mach-O file contained in this + universal binary file.

      +
      +
      +
      +
      +

      Return Value

      +

      An object file for the given architecture if it exists.

      +
      +
      +
      +
    • +
    • +
      + + + + Slice + +
      +
      +
      +
      +
      +
      +

      Represents an architecture-specific slice of a Mach-O universal binary +file.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public final class Slice : ObjectFile
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/MemoryBuffer.html b/docs/Classes/MemoryBuffer.html index e543a833..db74860d 100644 --- a/docs/Classes/MemoryBuffer.html +++ b/docs/Classes/MemoryBuffer.html @@ -8,18 +8,26 @@ + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    diff --git a/docs/Classes/Module.html b/docs/Classes/Module.html index 5a25e91f..3a384cae 100644 --- a/docs/Classes/Module.html +++ b/docs/Classes/Module.html @@ -8,18 +8,26 @@ + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    + + + +
    +
    + + +
    + +

    Module Flags

    +

    +
    +
    +
      +
    • +
      + + + + Flags + +
      +
      +
      +
      +
      +
      +

      Represents flags that describe information about the module for use by +an external entity e.g. the dynamic linker.

      +
      +

      Warning

      + Module flags are not a general runtime metadata infrastructure, +and may be stripped by LLVM. As of the current release, LLVM hardcodes +support for object-file emission of module flags related to +Objective-C. + +
      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public class Flags
      + +
      @@ -941,9 +2510,9 @@

      Return Value

    • @@ -951,15 +2520,14 @@

      Return Value

      -

      Searches for and retrieves a function with the given name in this module -if that name references an existing function.

      +

      Add a module-level flag to the module-level flags metadata.

      Declaration

      Swift

      -
      public func function(named name: String) -> Function?
      +
      public func addFlag(named name: String, value: IRMetadata, behavior: Flags.Behavior)
      @@ -975,17 +2543,135 @@

      Parameters

      -

      The name of the function to create.

      +

      The key for this flag.

      +
      + + + + + + value + + + +
      +

      The metadata node to insert as the value for this flag.

      +
      + + + + + + behavior + + + +
      +

      The resolution strategy to apply should the key for this +flag conflict with an existing flag.

      + +
    + +
  • + +
    +
    +
    +
    +
    +

    A convenience for inserting constant values as module-level flags.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func addFlag(named name: String, constant: IRConstant, behavior: Flags.Behavior)
    + +
    +
    -

    Return Value

    -

    A representation of the newly created function with the given -name or nil if such a representation could not be created.

    +

    Parameters

    + + + + + + + + + + + + + + + +
    + + name + + +
    +

    The key for this flag.

    +
    +
    + + value + + +
    +

    The constant value to insert as the metadata for this flag.

    +
    +
    + + behavior + + +
    +

    The resolution strategy to apply should the key for this +flag conflict with an existing flag.

    +
    +
    +
    +
    +
    +
  • +
  • +
    + + + + flags + +
    +
    +
    +
    +
    +
    +

    Retrieves the module-level flags, if they exist.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var flags: Flags? { get }
    + +
    @@ -995,8 +2681,8 @@

    Return Value

    diff --git a/docs/Classes/Module/Flags.html b/docs/Classes/Module/Flags.html new file mode 100644 index 00000000..0702564e --- /dev/null +++ b/docs/Classes/Module/Flags.html @@ -0,0 +1,747 @@ + + + + Flags Class Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    Flags

    +
    +
    + +
    public class Flags
    + +
    +
    +

    Represents flags that describe information about the module for use by +an external entity e.g. the dynamic linker.

    +
    +

    Warning

    + Module flags are not a general runtime metadata infrastructure, +and may be stripped by LLVM. As of the current release, LLVM hardcodes +support for object-file emission of module flags related to +Objective-C. + +
    + +
    +
    +
    +
      +
    • +
      + + + + Behavior + +
      +
      +
      +
      +
      +
      +

      Enumerates the supported behaviors for resolving collisions when two +module flags share the same key. These collisions can occur when the +different flags are inserted under the same key, or when modules +containing flags under the same key are merged.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public enum Behavior
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + Entry + +
      +
      +
      +
      +
      +
      +

      Represents an entry in the module flags structure.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public struct Entry
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + subscript(_:) + +
      +
      +
      +
      +
      +
      +

      Retrieves a flag at the given index.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public subscript(index: Int) -> Entry { get }
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + index + + +
      +

      The index to retrieve.

      +
      +
      +
      +
      +

      Return Value

      +

      An entry describing the flag at the given index.

      +
      +
      +
      +
    • +
    • +
      + + + + count + +
      +
      +
      +
      +
      +
      +

      Returns the number of module flag metadata entries.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var count: Int { get }
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/Module/Flags/Behavior.html b/docs/Classes/Module/Flags/Behavior.html new file mode 100644 index 00000000..87ded882 --- /dev/null +++ b/docs/Classes/Module/Flags/Behavior.html @@ -0,0 +1,779 @@ + + + + Behavior Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    Behavior

    +
    +
    + +
    public enum Behavior
    + +
    +
    +

    Enumerates the supported behaviors for resolving collisions when two +module flags share the same key. These collisions can occur when the +different flags are inserted under the same key, or when modules +containing flags under the same key are merged.

    + +
    +
    +
    +
      +
    • +
      + + + + error + +
      +
      +
      +
      +
      +
      +

      Emits an error if two values disagree, otherwise the resulting value +is that of the operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case error
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + warning + +
      +
      +
      +
      +
      +
      +

      Emits a warning if two values disagree. The result value will be the +operand for the flag from the first module being linked.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case warning
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + require + +
      +
      +
      +
      +
      +
      +

      Adds a requirement that another module flag be present and have a +specified value after linking is performed. The value must be a +metadata pair, where the first element of the pair is the ID of the +module flag to be restricted, and the second element of the pair is +the value the module flag should be restricted to. This behavior can +be used to restrict the allowable results (via triggering of an error) +of linking IDs with the Override behavior.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case require
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + override + +
      +
      +
      +
      +
      +
      +

      Uses the specified value, regardless of the behavior or value of the +other module. If both modules specify Override, but the values +differ, an error will be emitted.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case override
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + append + +
      +
      +
      +
      +
      +
      +

      Appends the two values, which are required to be metadata nodes.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case append
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + appendUnique + +
      +
      +
      +
      +
      +
      +

      Appends the two values, which are required to be metadata +nodes. However, duplicate entries in the second list are dropped +during the append operation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case appendUnique
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/Module/Flags/Entry.html b/docs/Classes/Module/Flags/Entry.html new file mode 100644 index 00000000..7e86068c --- /dev/null +++ b/docs/Classes/Module/Flags/Entry.html @@ -0,0 +1,683 @@ + + + + Entry Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    Entry

    +
    +
    + +
    public struct Entry
    + +
    +
    +

    Represents an entry in the module flags structure.

    + +
    +
    +
    +
      +
    • +
      + + + + behavior + +
      +
      +
      +
      +
      +
      +

      The conflict behavior of this flag.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var behavior: Behavior { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + key + +
      +
      +
      +
      +
      +
      +

      The key this flag was inserted with.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var key: String { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + metadata + +
      +
      +
      +
      +
      +
      +

      The metadata value associated with this flag.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var metadata: IRMetadata { get }
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/NamedMetadata.html b/docs/Classes/NamedMetadata.html new file mode 100644 index 00000000..fdac87e8 --- /dev/null +++ b/docs/Classes/NamedMetadata.html @@ -0,0 +1,766 @@ + + + + NamedMetadata Class Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    NamedMetadata

    +
    +
    + +
    public class NamedMetadata
    + +
    +
    +

    A NamedMetadata object represents a module-level metadata value identified +by a user-provided name. Named metadata is generated lazily when operands +are attached.

    + +
    +
    +
    +
      +
    • +
      + + + + module + +
      +
      +
      +
      +
      +
      +

      The module with which this named metadata is associated.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public let module: Module
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + name + +
      +
      +
      +
      +
      +
      +

      The name associated with this named metadata.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public let name: String
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + previous() + +
      +
      +
      +
      +
      +
      +

      Retrieves the previous alias in the module, if there is one.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func previous() -> NamedMetadata?
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + next() + +
      +
      +
      +
      +
      +
      +

      Retrieves the next alias in the module, if there is one.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func next() -> NamedMetadata?
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + operands + +
      +
      +
      +
      +
      +
      +

      Computes the operands of a named metadata node.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var operands: [IRMetadata] { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + addOperand(_:) + +
      +
      +
      +
      +
      +
      +

      Appends a metadata node as an operand.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func addOperand(_ op: IRMetadata)
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Classes/ObjectFile.html b/docs/Classes/ObjectFile.html index 0f961755..dc9a70c0 100644 --- a/docs/Classes/ObjectFile.html +++ b/docs/Classes/ObjectFile.html @@ -8,18 +8,26 @@ + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
  • - - -
    -
    - - -
    -
    • - - - FloatType + + + Struct
      @@ -468,32 +730,26 @@

      Declaration

      -

      FloatType enumerates representations of a floating value of a particular -bit width and semantics.

      +

      Represents struct types and operations.

      - See more

      Declaration

      Swift

      -
      public enum FloatType: IRType
      +
      public enum Struct : ConstantRepresentation
    • -
    -
    -
    -
    • @@ -501,34 +757,26 @@

      Declaration

      -

      Enumerates the calling conventions supported by LLVM.

      - -

      The raw values of this enumeration must match those in -llvm-c/Core.h

      +

      Represents vector types and operations.

      - See more

      Declaration

      Swift

      -
      public enum CallingConvention: UInt32
      +
      public enum Vector : ConstantRepresentation
    • -
    -
    -
    -
    • @@ -536,37 +784,32 @@

      Declaration

      -

      Enumerates the supported models of reference of thread-local variables.

      - -

      These models are listed from the most general, but least optimized, to the -fastest, but most restrictive.

      +

      DWARF expressions describe how to compute a value or specify a location. +They are expressed in terms of DWARF operations that operate on a stack of +values.

      -

      Documentation of these models quotes the Oracle Linker and Libraries -Guide.

      +

      A DWARF expression is encoded as a stream of operations, each consisting of +an opcode followed by zero or more literal operands.

      - See more + See more

      Declaration

      Swift

      -
      public enum ThreadLocalModel
      +
      public enum DWARFExpression
    • -
    -
    -
    -
    • @@ -574,16 +817,15 @@

      Declaration

      -

      Species the behavior that should occur on overflow during mathematical -operations.

      +

      Enumerates the kinds of attributes of LLVM functions and function parameters.

      - See more + See more

      Declaration

      Swift

      -
      public enum OverflowBehavior
      +
      public enum AttributeKind : String
      @@ -593,9 +835,9 @@

      Declaration

    • @@ -603,15 +845,15 @@

      Declaration

      -

      The condition codes available for integer comparison instructions.

      +

      Represents the possible indices of function attributes.

      - See more + See more

      Declaration

      Swift

      -
      public enum IntPredicate
      +
      public enum AttributeIndex : ExpressibleByIntegerLiteral, RawRepresentable
      @@ -621,9 +863,9 @@

      Declaration

    • @@ -631,15 +873,36 @@

      Declaration

      -

      The condition codes available for floating comparison instructions.

      +

      Enumerates the supported models of reference of thread-local variables.

      - See more +

      These models are listed from the most general, but least optimized, to the +fastest, but most restrictive in general, as architectural differences +play a role in determining the access patterns for thread-local storage.

      + +

      In general, support for thread-local storage in statically-linked +applications is limited: some platforms may not even define the behavior of +TLS in such cases. This is usually not an issue as statically-linked code +only ever has one TLS block, the offset of the variables within that block +is known, and support for additional dynamic loading of code in +statically-linked code is limited.

      + +

      Computing the thread-specific address of a TLS variable is usually a dynamic +process that relies on an ABI-defined function call (usually +__tls_get_addr) to do the heavy lifting.

      + +

      TLS access models fall into two classes: static and dynamic. Regardless of +the actual model used, the dynamic linker must process all relocations +for thread-local variables whenever the module is loaded. Some models, +therefore, provide for a decrease in the overall number of relocations at +a cost of restrictions on which modules can access variables.

      + + See more

      Declaration

      Swift

      -
      public enum RealPredicate
      +
      public enum ThreadLocalModel
      @@ -649,9 +912,9 @@

      Declaration

    • @@ -659,24 +922,15 @@

      Declaration

      -

      AtomicOrdering enumerates available memory ordering semantics.

      - -

      Atomic instructions (cmpxchg, atomicrmw, fence, atomic load, and -atomic store) take ordering parameters that determine which other atomic -instructions on the same address they synchronize with. These semantics are -borrowed from Java and C++0x, but are somewhat more colloquial. If these -descriptions aren’t precise enough, check those specs (see spec references -in the atomics guide). fence instructions treat these orderings somewhat -differently since they don’t take an address. See that instruction’s -documentation for details.

      +

      Enumerates the kind of metadata nodes.

      - See more + See more

      Declaration

      Swift

      -
      public enum AtomicOrdering: Comparable
      +
      public enum IRMetadataKind
      @@ -686,9 +940,9 @@

      Declaration

    • @@ -696,32 +950,27 @@

      Declaration

      -

      AtomicReadModifyWriteOperation enumerates the kinds of supported atomic -read-write-modify operations.

      +

      Enumerates the kinds of values present in LLVM IR.

      - See more + See more

      Declaration

      Swift

      -
      public enum AtomicReadModifyWriteOperation
      +
      public enum IRValueKind
    • -
    -
    -
    -
    • - + - JITError + JITError
      @@ -738,23 +987,19 @@

      Declaration

      Declaration

      Swift

      -
      public enum JITError: Error, CustomStringConvertible
      +
      public enum JITError : Error, CustomStringConvertible
    - - -
    -
    • @@ -770,7 +1015,7 @@

      Declaration

      Declaration

      Swift

      -
      public enum Visibility
      +
      public enum Visibility
      @@ -780,9 +1025,9 @@

      Declaration

    • - + - Linkage + Linkage
      @@ -799,7 +1044,7 @@

      Declaration

      Declaration

      Swift

      -
      public enum Linkage
      +
      public enum Linkage
      @@ -809,9 +1054,9 @@

      Declaration

    • @@ -828,23 +1073,57 @@

      Declaration

      Declaration

      Swift

      -
      public enum StorageClass
      +
      public enum StorageClass
      + +
      +
      + +
    + +
  • +
    + + + + UnnamedAddressKind + +
    +
    +
    +
    +
    +
    +

    Enumerates values representing whether or not this global value’s address +is significant in this module or the program at large. A global value’s +address is considered significant if it is referenced by any module in the +final program.

    + +

    This attribute is intended to be used only by the code generator and LTO to +allow the linker to decide whether the global needs to be in the symbol +table. Constant global values with unnamed addresses and identical +initializers may be merged by LLVM. Note that a global value with an +unnamed address may be merged with a global value with a significant address +resulting in a global value with a significant address.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public enum UnnamedAddressKind
  • - - -
    -
    • @@ -861,7 +1140,120 @@

      Declaration

      Declaration

      Swift

      -
      public enum MemoryBufferError: Error
      +
      public enum MemoryBufferError : Error
      + +
      +
      + +
    + +
  • +
    + + + + DWARFSourceLanguage + +
    +
    +
    +
    +
    +
    +

    Source languages known to DWARF.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public enum DWARFSourceLanguage
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + DWARFTag + +
    +
    +
    +
    +
    +
    +

    Enumerates the supported identifying tags for corresponding DWARF +Debugging Information Entries (DIEs) known to LLVM.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public enum DWARFTag : UInt32
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    Describes how a base type is encoded and to be interpreted by a debugger.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public enum DIAttributeTypeEncoding
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + DWARFEmissionKind + +
    +
    +
    +
    +
    +
    +

    The amount of debug information to emit.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public enum DWARFEmissionKind
    @@ -871,13 +1263,22 @@

    Declaration

    +
    + + +
    + +

    Module Errors

    +

    +
    +
    • @@ -894,23 +1295,48 @@

      Declaration

      Declaration

      Swift

      -
      public enum ModuleError: Error, CustomStringConvertible
      +
      public enum ModuleError : Error, CustomStringConvertible
  • - - -
    -
    • - + + + BinaryFileError + +
      +
      +
      +
      +
      +
      +

      Enumerates the possible failures that can be thrown initializing +a MemoryBuffer.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public enum BinaryFileError : Error
      + +
      +
      +
      +
      +
    • +
    • +
      + + - OpCode + OpCode
      @@ -926,23 +1352,198 @@

      Declaration

      Declaration

      Swift

      -
      public enum OpCode
      +
      public enum OpCode : CaseIterable
    - - -
    -
    • - - - FunctionPass + + + OverflowBehavior + +
      +
      +
      +
      +
      +
      +

      Species the behavior that should occur on overflow during mathematical +operations.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public enum OverflowBehavior
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + IntPredicate + +
      +
      +
      +
      +
      +
      +

      The condition codes available for integer comparison instructions.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public enum IntPredicate
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + RealPredicate + +
      +
      +
      +
      +
      +
      +

      The condition codes available for floating comparison instructions.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public enum RealPredicate
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + AtomicOrdering + +
      +
      +
      +
      +
      +
      +

      AtomicOrdering enumerates available memory ordering semantics.

      + +

      Atomic instructions (cmpxchg, atomicrmw, fence, atomic load, and +atomic store) take ordering parameters that determine which other atomic +instructions on the same address they synchronize with. These semantics are +borrowed from Java and C++0x, but are somewhat more colloquial. If these +descriptions aren’t precise enough, check those specs (see spec references +in the atomics guide). fence instructions treat these orderings somewhat +differently since they don’t take an address. See that instruction’s +documentation for details.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public enum AtomicOrdering : Comparable
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      AtomicReadModifyWriteOperation enumerates the kinds of supported atomic +read-write-modify operations.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public enum AtomicReadModifyWriteOperation
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + InlineAssemblyDialect + +
      +
      +
      +
      +
      +
      +

      Enumerates the dialects of inline assembly LLVM’s parsers can handle.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public enum InlineAssemblyDialect
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + Pass
      @@ -952,29 +1553,25 @@

      Declaration

      A subset of supported LLVM IR optimizer passes.

      - See more + See more

      Declaration

      Swift

      -
      public enum FunctionPass
      +
      public enum Pass
    • -
    -
    -
    -
    • @@ -991,7 +1588,7 @@

      Declaration

      Declaration

      Swift

      -
      public enum ByteOrder
      +
      public enum ByteOrder
      @@ -1001,9 +1598,9 @@

      Declaration

    • @@ -1021,7 +1618,7 @@

      Declaration

      Declaration

      Swift

      -
      public enum CodeGenOptLevel
      +
      public enum CodeGenOptLevel
      @@ -1031,9 +1628,9 @@

      Declaration

    • @@ -1043,13 +1640,13 @@

      Declaration

      The relocation model types supported by LLVM.

      - See more + See more

      Declaration

      Swift

      -
      public enum RelocMode
      +
      public enum RelocationModel
      @@ -1059,9 +1656,9 @@

      Declaration

    • @@ -1083,23 +1680,19 @@

      Declaration

      Declaration

      Swift

      -
      public enum CodeModel
      +
      public enum CodeModel
    - - -
    -
    • @@ -1115,7 +1708,7 @@

      Declaration

      Declaration

      Swift

      -
      public enum CodegenFileType
      +
      public enum CodegenFileType
      @@ -1125,9 +1718,9 @@

      Declaration

    • @@ -1143,7 +1736,7 @@

      Declaration

      Declaration

      Swift

      -
      public enum TargetMachineError: Error, CustomStringConvertible
      +
      public enum TargetMachineError : Error, CustomStringConvertible
      @@ -1155,8 +1748,8 @@

      Declaration

    diff --git a/docs/Enums/AtomicOrdering.html b/docs/Enums/AtomicOrdering.html index 0b71afa0..881b6cec 100644 --- a/docs/Enums/AtomicOrdering.html +++ b/docs/Enums/AtomicOrdering.html @@ -1,27 +1,35 @@ - AtomicOrdering Enum Reference + AtomicOrdering Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • @@ -412,23 +650,19 @@

      Declaration

      Declaration

      Swift

      -
      case unordered
      +
      case unordered
    - - -
    -
    • @@ -459,23 +693,19 @@

      Declaration

      Declaration

      Swift

      -
      case monotonic
      +
      case monotonic
    - - -
    -
    • - + - acquire + acquire
      @@ -495,23 +725,19 @@

      Declaration

      Declaration

      Swift

      -
      case acquire
      +
      case acquire
    - - -
    -
    • - + - release + release
      @@ -533,23 +759,19 @@

      Declaration

      Declaration

      Swift

      -
      case release
      +
      case release
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    • - + - add + add
      @@ -393,7 +631,7 @@

      Declaration

      Add a value and return the old one

      -
      *ptr = *ptr + val
      +
      *ptr = *ptr + val
       
      @@ -401,23 +639,19 @@

      Declaration

      Declaration

      Swift

      -
      case add
      +
      case add
    - - -
    -
    • - + - sub + sub
      @@ -426,7 +660,7 @@

      Declaration

      Subtract a value and return the old one

      -
      *ptr = *ptr - val
      +
      *ptr = *ptr - val
       
      @@ -434,23 +668,19 @@

      Declaration

      Declaration

      Swift

      -
      case sub
      +
      case sub
    - - -
    -
    • - + - and + and
      @@ -459,7 +689,7 @@

      Declaration

      And a value and return the old one

      -
      *ptr = *ptr & val
      +
      *ptr = *ptr & val
       
      @@ -467,23 +697,19 @@

      Declaration

      Declaration

      Swift

      -
      case and
      +
      case and
    - - -
    -
    • - + - nand + nand
      @@ -492,7 +718,7 @@

      Declaration

      Not-And a value and return the old one

      -
      *ptr = ~(*ptr & val)
      +
      *ptr = ~(*ptr & val)
       
      @@ -500,23 +726,19 @@

      Declaration

      Declaration

      Swift

      -
      case nand
      +
      case nand
    - - -
    -
    • - + - or + or
      @@ -525,7 +747,7 @@

      Declaration

      OR a value and return the old one

      -
      *ptr = *ptr | val
      +
      *ptr = *ptr | val
       
      @@ -533,23 +755,19 @@

      Declaration

      Declaration

      Swift

      -
      case or
      +
      case or
    - - -
    -
    • - + - xor + xor
      @@ -558,7 +776,7 @@

      Declaration

      Xor a value and return the old one

      -
      *ptr = *ptr ^ val
      +
      *ptr = *ptr ^ val
       
      @@ -566,23 +784,19 @@

      Declaration

      Declaration

      Swift

      -
      case xor
      +
      case xor
    - - -
    -
    • - + - max + max
      @@ -592,8 +806,8 @@

      Declaration

      Sets the value if it’s greater than the original using a signed comparison and return the old one.

      -
      // Using a signed comparison
      -*ptr = *ptr > val ? *ptr : val
      +
      // Using a signed comparison
      +*ptr = *ptr > val ? *ptr : val
       
      @@ -601,23 +815,19 @@

      Declaration

      Declaration

      Swift

      -
      case max
      +
      case max
    - - -
    -
    • - + - min + min
      @@ -627,8 +837,8 @@

      Declaration

      Sets the value if it’s Smaller than the original using a signed comparison and return the old one.

      -
      // Using a signed comparison
      -*ptr = *ptr < val ? *ptr : val
      +
      // Using a signed comparison
      +*ptr = *ptr < val ? *ptr : val
       
      @@ -636,23 +846,19 @@

      Declaration

      Declaration

      Swift

      -
      case min
      +
      case min
    - - -
    -
    • - + - umax + umax
      @@ -662,8 +868,8 @@

      Declaration

      Sets the value if it’s greater than the original using an unsigned comparison and return the old one.

      -
      // Using an unsigned comparison
      -*ptr = *ptr > val ? *ptr : val
      +
      // Using an unsigned comparison
      +*ptr = *ptr > val ? *ptr : val
       
      @@ -671,23 +877,19 @@

      Declaration

      Declaration

      Swift

      -
      case umax
      +
      case umax
    - - -
    -
    • - + - umin + umin
      @@ -697,8 +899,8 @@

      Declaration

      Sets the value if it’s greater than the original using an unsigned comparison and return the old one.

      -
      // Using an unsigned comparison
      -*ptr = *ptr < val ? *ptr : val
      +
      // Using an unsigned comparison
      +*ptr = *ptr < val ? *ptr : val
       
      @@ -706,38 +908,7 @@

      Declaration

      Declaration

      Swift

      -
      case umin
      - -
      -
      - -
    - - - -
    -
    diff --git a/docs/Enums/AttributeKind.html b/docs/Enums/AttributeKind.html new file mode 100644 index 00000000..c7205237 --- /dev/null +++ b/docs/Enums/AttributeKind.html @@ -0,0 +1,2190 @@ + + + + AttributeKind Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    AttributeKind

    +
    +
    + +
    public enum AttributeKind : String
    + +
    +
    +

    Enumerates the kinds of attributes of LLVM functions and function parameters.

    + +
    +
    +
    +
      +
    • +
      + + + + alignstack + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that, when emitting the prologue and epilogue, +the backend should forcibly align the stack pointer.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case alignstack
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + allocsize + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the annotated function will always return +at least a given number of bytes (or null).

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case allocsize
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + alwaysinline + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the inliner should attempt to inline this +function into callers whenever possible, ignoring any active inlining +size threshold for this caller.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case alwaysinline
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + builtin + +
      +
      +
      +
      +
      +
      +

      This indicates that the callee function at a call site should be +recognized as a built-in function, even though the function’s declaration +uses the nobuiltin attribute

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case builtin
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + cold + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that this function is rarely called.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case cold
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + convergent + +
      +
      +
      +
      +
      +
      +

      In some parallel execution models, there exist operations that cannot be +made control-dependent on any additional values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case convergent
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + inaccessiblememonly + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the function may only access memory that is +not accessible by the module being compiled.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case inaccessiblememonly
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      This attribute indicates that the function may only access memory that is +either not accessible by the module being compiled, or is pointed to by +its pointer arguments.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case inaccessiblememOrArgmemonly = "inaccessiblemem_or_argmemonly"
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + inlinehint + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the source code contained a hint that inlin +inlining this function is desirable (such as the “inline” keyword in +C/C++).

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case inlinehint
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + jumptable + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the function should be added to a +jump-instruction table at code-generation time, and that all +address-taken references to this function should be replaced with a +reference to the appropriate jump-instruction-table function pointer.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case jumptable
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + minsize + +
      +
      +
      +
      +
      +
      +

      This attribute suggests that optimization passes and code generator +passes make choices that keep the code size of this function as small as +possible and perform optimizations that may sacrifice runtime performance +in order to minimize the size of the generated code.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case minsize
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + naked + +
      +
      +
      +
      +
      +
      +

      This attribute disables prologue / epilogue emission for the function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case naked
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + noJumpTables + +
      +
      +
      +
      +
      +
      +

      When this attribute is set to true, the jump tables and lookup tables +that can be generated from a switch case lowering are disabled.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case noJumpTables = "no-jump-tables"
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + nobuiltin + +
      +
      +
      +
      +
      +
      +

      This indicates that the callee function at a call site is not recognized +as a built-in function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case nobuiltin
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + noduplicate + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that calls to the function cannot be duplicated.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case noduplicate
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + noimplicitfloat + +
      +
      +
      +
      +
      +
      +

      This attributes disables implicit floating point instructions.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case noimplicitfloat
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + noinline + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the inliner should never inline this +function in any situation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case noinline
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + nonlazybind + +
      +
      +
      +
      +
      +
      +

      This attribute suppresses lazy symbol binding for the function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case nonlazybind
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + noredzone + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the code generator should not use a red +zone, even if the target-specific ABI normally permits it.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case noredzone
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + noreturn + +
      +
      +
      +
      +
      +
      +

      This function attribute indicates that the function never returns +normally.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case noreturn
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + norecurse + +
      +
      +
      +
      +
      +
      +

      This function attribute indicates that the function does not call itself +either directly or indirectly down any possible call path.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case norecurse
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + nounwind + +
      +
      +
      +
      +
      +
      +

      This function attribute indicates that the function never raises an +exception.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case nounwind
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + optnone + +
      +
      +
      +
      +
      +
      +

      This function attribute indicates that most optimization passes will skip +this function, with the exception of interprocedural optimization passes.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case optnone
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + optsize + +
      +
      +
      +
      +
      +
      +

      This attribute suggests that optimization passes and code generator +passes make choices that keep the code size of this function low, and +otherwise do optimizations specifically to reduce code size as long as +they do not significantly impact runtime performance.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case optsize
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + readnone + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the function computes its result (or +decides to unwind an exception) based strictly on its arguments, without +dereferencing any pointer arguments or otherwise accessing any mutable +state (e.g. memory, control registers, etc) visible to caller functions.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case readnone
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + readonly + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the function does not write through any +pointer arguments (including byval arguments) or otherwise modify any +state (e.g. memory, control registers, etc) visible to caller functions.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case readonly
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + writeonly + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the function may write to but does not read +read from memory.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case writeonly
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + argmemonly + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the only memory accesses inside function +are loads and stores from objects pointed to by its pointer-typed +arguments, with arbitrary offsets.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case argmemonly
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + returnsTwice + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that this function can return twice.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case returnsTwice = "returns_twice"
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + safestack + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that SafeStack protection is enabled for this +function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case safestack
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + sanitizeAddress + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that AddressSanitizer checks (dynamic address +safety analysis) are enabled for this function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case sanitizeAddress = "sanitize_address"
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + sanitizeMemory + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that MemorySanitizer checks (dynamic detection +of accesses to uninitialized memory) are enabled for this function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case sanitizeMemory = "sanitize_memory"
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + sanitizeThread + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that ThreadSanitizer checks (dynamic thread +safety analysis) are enabled for this function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case sanitizeThread = "sanitize_thread"
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + sanitizeHWAddress + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that HWAddressSanitizer checks (dynamic address +safety analysis based on tagged pointers) are enabled for this function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case sanitizeHWAddress = "sanitize_hwaddress"
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + speculatable + +
      +
      +
      +
      +
      +
      +

      This function attribute indicates that the function does not have any +effects besides calculating its result and does not have undefined +behavior.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case speculatable
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ssp + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the function should emit a stack smashing +protector.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case ssp
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + sspreq + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the function should always emit a stack +smashing protector

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case sspreq
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + sspstrong + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the function should emit a stack smashing +protector.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case sspstrong
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + strictfp + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the function was called from a scope that +requires strict floating point semantics.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case strictfp
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + uwtable + +
      +
      +
      +
      +
      +
      +

      This attribute indicates that the ABI being targeted requires that an +unwind table entry be produced for this function even if we can show +that no exceptions passes by it.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case uwtable
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + zeroext + +
      +
      +
      +
      +
      +
      +

      This indicates to the code generator that the parameter or return value +should be zero-extended to the extent required by the target’s ABI by the +caller (for a parameter) or the callee (for a return value).

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case zeroext
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + signext + +
      +
      +
      +
      +
      +
      +

      This indicates to the code generator that the parameter or return value +should be sign-extended to the extent required by the target’s ABI (which +is usually 32-bits) by the caller (for a parameter) or the callee (for a +return value).

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case signext
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + inreg + +
      +
      +
      +
      +
      +
      +

      This indicates that this parameter or return value should be treated in a +special target-dependent fashion while emitting code for a function call +or return.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case inreg
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + byval + +
      +
      +
      +
      +
      +
      +

      This indicates that the pointer parameter should really be passed by +value to the function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case byval
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + inalloca + +
      +
      +
      +
      +
      +
      +

      The inalloca argument attribute allows the caller to take the address of +outgoing stack arguments

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case inalloca
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + sret + +
      +
      +
      +
      +
      +
      +

      This indicates that the pointer parameter specifies the address of a +structure that is the return value of the function in the source program.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case sret
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + align + +
      +
      +
      +
      +
      +
      +

      This indicates that the pointer value may be assumed by the optimizer to +have the specified alignment.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case align
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + noalias + +
      +
      +
      +
      +
      +
      +

      This indicates that objects accessed via pointer values based on the +argument or return value are not also accessed, during the execution of +the function, via pointer values not based on the argument or return +value.

      + +

      The noalias attribute may appear in one of two location: on arguments +types or on return types. On argument types, noalias acts like the +restrict keyword in C and C++ and implies that no other pointer value +points to this object. On return types, noalias implies that the +returned pointer is not aliased by any other pointer in the program.

      + +

      Practically, this allows LLVM to reorder accesses to this memory.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case noalias
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + nocapture + +
      +
      +
      +
      +
      +
      +

      This indicates that the callee does not make any copies of the pointer +that outlive the callee itself.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case nocapture
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + nest + +
      +
      +
      +
      +
      +
      +

      This indicates that the pointer parameter can be excised using the +trampoline intrinsics.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case nest
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + returned + +
      +
      +
      +
      +
      +
      +

      This indicates that the function always returns the argument as its +return value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case returned
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + nonnull + +
      +
      +
      +
      +
      +
      +

      This indicates that the parameter or return pointer is not null.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case nonnull
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + dereferenceable + +
      +
      +
      +
      +
      +
      +

      This indicates that the parameter or return pointer is dereferenceable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case dereferenceable
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + dereferenceableOrNull + +
      +
      +
      +
      +
      +
      +

      This indicates that the parameter or return value isn’t both non-null and +non-dereferenceable (up to n bytes) at the same time.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case dereferenceableOrNull = "dereferenceable_or_null"
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + swiftself + +
      +
      +
      +
      +
      +
      +

      This indicates that the parameter is the self/context parameter.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case swiftself
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + swifterror + +
      +
      +
      +
      +
      +
      +

      This attribute is motivated to model and optimize Swift error handling.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case swifterror
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Enums/BinaryFileError.html b/docs/Enums/BinaryFileError.html new file mode 100644 index 00000000..a1e95b0f --- /dev/null +++ b/docs/Enums/BinaryFileError.html @@ -0,0 +1,630 @@ + + + + BinaryFileError Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    BinaryFileError

    +
    +
    + +
    public enum BinaryFileError : Error
    + +
    +
    +

    Enumerates the possible failures that can be thrown initializing +a MemoryBuffer.

    + +
    +
    +
    +
      +
    • +
      + + + + couldNotCreate(_:) + +
      +
      +
      +
      +
      +
      +

      The MemoryBuffer failed to be initialized for a specific reason.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case couldNotCreate(String)
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Enums/ByteOrder.html b/docs/Enums/ByteOrder.html index e8798fe8..c2d75118 100644 --- a/docs/Enums/ByteOrder.html +++ b/docs/Enums/ByteOrder.html @@ -1,27 +1,35 @@ - ByteOrder Enum Reference + ByteOrder Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • @@ -398,8 +636,8 @@

      Declaration

      Big-endian byte order. In a big-endian platform, the most significant bytes come before the least significant bytes in a series, so the 16-bit number 1234 would look like:

      -
      00000100 11010010
      -^ higher  ^ lower order
      +
      00000100 11010010
      +^ higher  ^ lower order
       

      Big-endian byte order is the most natural order for humans to understand.

      @@ -409,7 +647,7 @@

      Declaration

      Declaration

      Swift

      -
      case bigEndian
      +
      case bigEndian
      @@ -421,8 +659,8 @@

      Declaration

    diff --git a/docs/Enums/CallingConvention.html b/docs/Enums/CallingConvention.html index 34af7a4c..f8b92f87 100644 --- a/docs/Enums/CallingConvention.html +++ b/docs/Enums/CallingConvention.html @@ -1,27 +1,35 @@ - CallingConvention Enum Reference + CallingConvention Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • - + - fast + fast
      @@ -393,30 +628,33 @@

      Declaration

      This calling convention attempts to make calls as fast as possible -(e.g. by passing things in registers).

      +(e.g. by passing things in registers). This calling convention +allows the target to use whatever tricks it wants to produce fast +code for the target, without having to conform to an externally +specified ABI (Application Binary Interface). Tail calls can only +be optimized when this, theghcor thehiPE` convention is +used. This calling convention does not support varargs and requires the +prototype of all callees to exactly match the prototype of the function +definition.

      Declaration

      Swift

      -
      case fast = 8
      +
      case fast
    • -
    -
    -
    -
    • - + - cold + cold
      @@ -424,33 +662,120 @@

      Declaration

      -

      This calling convention attempts to make code in the caller as efficient -as possible under the assumption that the call is not commonly executed.
      -As such, these calls often preserve all registers so that the call does -not break any live ranges in the caller side.

      +

      This calling convention attempts to make code in the caller as +efficient as possible under the assumption that the call is not +commonly executed. As such, these calls often preserve all registers +so that the call does not break any live ranges in the caller side. +This calling convention does not support varargs and requires the +prototype of all callees to exactly match the prototype of the +function definition. Furthermore the inliner doesn’t consider such +function calls for inlining.

      Declaration

      Swift

      -
      case cold = 9
      +
      case cold
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ghc + +
      +
      +
      +
      +
      +
      +

      This calling convention has been implemented specifically for use by +the Glasgow Haskell Compiler (GHC).

      + +

      It passes everything in registers, going to extremes to achieve this +by disabling callee save registers. This calling convention should +not be used lightly but only for specific situations such as an +alternative to the register pinning performance technique often +used when implementing functional programming languages. At the +moment only X86 supports this convention and it has the following +limitations:

      + +
        +
      • On X86-32 only supports up to 4 bit type parameters. No +floating-point types are supported.
      • +
      • On X86-64 only supports up to 10 bit type parameters and 6 +floating-point parameters.
      • +
      + +

      This calling convention supports `tail call +optimization but requires both the caller and callee are using it.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case ghc
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + hiPE + +
      +
      +
      +
      +
      +
      +

      This calling convention has been implemented specifically for use by +the High-Performance Erlang (HiPE) compiler, the +native code compiler of the `Ericsson’s Open Source Erlang/OTP +system.

      + +

      It uses more registers for argument passing than the ordinary C calling +convention and defines no callee-saved registers. The calling +convention properly supports tail call optimization but requires that +both the caller and the callee use it.

      + +

      It uses a register pinning mechanism, similar to GHC’s convention, for +keeping frequently accessed runtime components pinned to specific hardware +registers.

      + +

      At the moment only X86 supports this convention (both 32 and 64 bit).

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case hiPE
    • -
    -
    -
    -
    • - + - webKitJS + webKitJS
      @@ -458,30 +783,28 @@

      Declaration

      -

      Calling convention for stack based JavaScript calls.

      +

      This calling convention has been implemented for WebKit FTL JIT. It passes +arguments on the stack right to left (as cdecl does), and returns a value +in the platform’s customary return register.

      Declaration

      Swift

      -
      case webKitJS = 12
      +
      case webKitJS
    • -
    -
    -
    -
    • - + - anyReg + anyReg
      @@ -489,31 +812,34 @@

      Declaration

      -

      Calling convention for dynamic register based calls +

      Calling convention for dynamic register based calls (e.g. stackmap and patchpoint intrinsics).

      +

      This is a special convention that supports patching an arbitrary code +sequence in place of a call site. This convention forces the call +arguments into registers but allows them to be dynamically +allocated. This can currently only be used with calls to +llvm.experimental.patchpoint because only this intrinsic records +the location of its arguments in a side table.

      +

      Declaration

      Swift

      -
      case anyReg = 13
      +
      case anyReg
    • -
    -
    -
    -
    • - - - x86Stdcall + + + preserveMost
      @@ -521,33 +847,64 @@

      Declaration

      -

      The calling conventions mostly used by the Win32 API.

      +

      Calling convention for runtime calls that preserves most registers.

      -

      It is basically the same as the C convention with the difference in that -the callee is responsible for popping the arguments from the stack.

      +

      This calling convention attempts to make the code in the caller as +unintrusive as possible. This convention behaves identically to the c +calling convention on how arguments and return values are passed, but it +uses a different set of caller/callee-saved registers. This alleviates the +burden of saving and recovering a large register set before and after the +call in the caller. If the arguments are passed in callee-saved registers, +then they will be preserved by the callee across the call. This doesn’t +apply for values returned in callee-saved registers.

      + +

      On X86-64 the callee preserves all general purpose registers, except for +R11. R11 can be used as a scratch register. Floating-point registers +(XMMs/YMMs) are not preserved and need to be saved by the caller.

      + +

      The idea behind this convention is to support calls to runtime functions +that have a hot path and a cold path. The hot path is usually a small +piece of code that doesn’t use many registers. The cold path might need to +call out to another function and therefore only needs to preserve the +caller-saved registers, which haven’t already been saved by the caller.

      + +

      The preserveMost calling convention is very similar to the cold +calling convention in terms of caller/callee-saved registers, but they are +used for different types of function calls. cold is for function calls +that are rarely executed, whereas preserveMost function calls are +intended to be on the hot path and definitely executed a lot. Furthermore +preserveMost doesn’t prevent the inliner from inlining the function +call.

      + +

      This calling convention will be used by a future version of the +Objective-C runtime and should therefore still be considered experimental +at this time.

      + +

      Although this convention was created to optimize certain runtime calls to +the ObjectiveC runtime, it is not limited to this runtime and might be +used by other runtimes in the future too.

      + +

      The current implementation only supports X86-64, but the intention is to +support more architectures in the future.

      Declaration

      Swift

      -
      case x86Stdcall = 64
      +
      case preserveMost
    • -
    -
    -
    -
    • - - - x86Fastcall + + + preserveAll
      @@ -555,17 +912,1098 @@

      Declaration

      -

      Fast analog of x86Stdcall.

      +

      This calling convention attempts to make the code in the caller even less +intrusive than the preserveMost calling convention. This calling +convention also behaves identical to the c calling convention on how +arguments and return values are passed, but it uses a different set of +caller/callee-saved registers. This removes the burden of saving and +recovering a large register set before and after the call in the caller.

      -

      Passes first two arguments in ECX:EDX registers, others via the stack. -The callee is responsible for stack cleaning.

      +

      If the arguments are passed in callee-saved registers, then they will be +preserved by the callee across the call. This doesn’t apply for values +returned in callee-saved registers.

      + +
        +
      • On X86-64 the callee preserves all general purpose registers, except for +R11. R11 can be used as a scratch register. Furthermore it also preserves +all floating-point registers (XMMs/YMMs).
      • +
      + +

      The idea behind this convention is to support calls to runtime functions +that don’t need to call out to any other functions.

      + +

      This calling convention, like the preserveMost calling convention, +will be used by a future version of the ObjectiveC runtime and should be +considered experimental at this time.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case preserveAll
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + swift + +
      +
      +
      +
      +
      +
      +

      Calling convention for Swift.

      + +
        +
      • On X86-64 RCX and R8 are available for additional integer returns, +and XMM2 and XMM3 are available for additional FP/vector returns.
      • +
      • On iOS platforms, we use the armAAPCSVFP calling convention.
      • +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case swift
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      The calling convention for accessors to C++-style thread-local storage.

      + +

      The access function generally has an entry block, an exit block +and an initialization block that is run at the first time. The entry and +exit blocks can access a few TLS IR variables, each access will be lowered +to a platform-specific sequence.

      + +

      This calling convention aims to minimize overhead in the caller by +preserving as many registers as possible (all the registers that are +perserved on the fast path, composed of the entry and exit blocks).

      + +

      This calling convention behaves identical to the C calling convention on +how arguments and return values are passed, but it uses a different set of +caller/callee-saved registers.

      + +

      Given that each platform has its own lowering sequence, hence its own set +of preserved registers, we can’t use the existing preserveMost.

      + +
        +
      • On X86-64 the callee preserves all general purpose registers, except for +RDI and RAX.
      • +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case cxxFastThreadLocalStorage
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + x86StandardCall + +
      +
      +
      +
      +
      +
      +

      The calling conventions mostly used by the Win32 API.

      + +

      It is basically the same as the C convention with the difference in that +the callee is responsible for popping the arguments from the stack.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case x86StandardCall
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + x86FastCall + +
      +
      +
      +
      +
      +
      +

      “Fast” analog of x86Stdcall.

      + +

      Passes first two arguments in ECX:EDX registers, others via the stack. +The callee is responsible for stack cleaning.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case x86FastCall
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + armAPCS + +
      +
      +
      +
      +
      +
      +

      Short for “ARM Procedure Calling Standard” calling convention (obsolete, +but still used on some targets).

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case armAPCS
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + armAAPCS + +
      +
      +
      +
      +
      +
      +

      Short for “ARM Architecture Procedure Calling Standard” calling +convention. This is often referred to as EABI - though this terminology +can be confusing for those that remember EABI from PowerPC.

      + +

      armAAPCS is the modern incarnation of armAPCS. It enables a number of +desirable optimizations over armAPCS such as tighter packing of +structures and (emulated) floating point instructions. armAPCS suffered +a 10x performance penalty in environments without a floating point +co-processor, as floating routines would be implemented by trapping to +software implementations in the kernel.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case armAAPCS
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + armAAPCSVFP + +
      +
      +
      +
      +
      +
      +

      Same as armAAPCS, but uses hardware floating point ABI. On +ARM architectures before ARMv8, these instructions are implemented as +co-processor extensions.

      + +

      Despite VFP being short for “Vector Floating Point”, processing of data +is entirely sequential. VFP does not perform actual vector computing +in the usual sense (SIMD), and is generally replaced by NEON intrinsics.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case armAAPCSVFP
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + msp430Interrupt + +
      +
      +
      +
      +
      +
      +

      Calling convention used for MSP430 interrupt service routines (ISRs).

      + +

      ISRs may not accept or return arguments in registers. They should ideally +save all registers when they are first invoked and must clean up before +returning with the special RETI instruction. LLVM will trap if any of +these invariants are violated.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case msp430Interrupt
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + x86ThisCall + +
      +
      +
      +
      +
      +
      +

      Similar to x86Stdcall.

      + +
        +
      • On x86_64 it passes the first argument (a pointer to this in C++) in +ECX and the others via the stack from right to left. The callee is +responsible for popping the arguments from the stack.
      • +
      + +

      MSVC uses this by default for methods in its ABI for all non-variadic +member method calls.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case x86ThisCall
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ptxKernelFunction + +
      +
      +
      +
      +
      +
      +

      Calling convention for Parallel Thread Execution (PTX) kernel functions.

      + +

      In PTX, there are two types of functions: device functions, which are only +callable by device code, and kernel functions, which are callable by host +code. Use this calling convention for kernel functions.

      + +

      The parameter (.param) state space is used to pass input arguments +from the host to the kernel, to declare formal input and return +parameters for device functions called from within kernel execution, and +to declare locally-scoped byte array variables that serve as function +call arguments, typically for passing large structures by value to a +function.

      + +

      Kernel function parameters differ from device function parameters in terms +of access and sharing (read-only versus read-write, per-kernel versus +per-thread).

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case ptxKernelFunction
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ptxDeviceFunction + +
      +
      +
      +
      +
      +
      +

      Calling convention for Parallel Thread Execution (PTX) device functions.

      + +

      Passes all arguments in register or parameter space.

      + +

      Registers (.reg state space) are fast storage locations. The number of +registers is limited, and will vary from platform to platform. When the +limit is exceeded, register variables will be spilled to memory, causing +changes in performance.

      + +

      Device function parameters differ from kernel function parameters in that +they may not necessarily be directly addressable. Because the exact +location of argument values is implementation-defined, requesting the +address of a device argument is generally not supported.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case ptxDeviceFunction
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + spirDeviceFunction + +
      +
      +
      +
      +
      +
      +

      Calling convention for SPIR non-kernel device functions.

      + +

      No lowering or expansion of arguments. +Structures are passed as a pointer to a struct with the byval attribute. +Functions can only call SPIR_FUNC and SPIR_KERNEL functions. +Functions can only have zero or one return values. +Variable arguments are not allowed, except for printf. +How arguments/return values are lowered are not specified. +Functions are only visible to the devices.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case spirDeviceFunction
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + spirKernelFunction + +
      +
      +
      +
      +
      +
      +

      Calling convention for SPIR kernel functions.

      + +

      Inherits the restrictions of .spirFunction, except +Cannot have non-void return values. +Cannot have variable arguments. +Can also be called by the host. +Is externally visible.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case spirKernelFunction
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + intelOpenCLBuiltin + +
      +
      +
      +
      +
      +
      +

      Calling conventions for Intel OpenCL built-ins.

      + +

      Extends the x86_32 C ABI for passing and returning values by a set of +high-bitwidth registers for passing arguments and returning values from +functions, and a set of mask registers.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case intelOpenCLBuiltin
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + x8664SystemV + +
      +
      +
      +
      +
      +
      +

      The C convention as specified in the x86-64 supplement to the +System V ABI, used on most non-Windows systems.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case x8664SystemV
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + win64 + +
      +
      +
      +
      +
      +
      +

      The C convention as implemented on Windows/x86-64 and +AArch64. This convention differs from the more common +x8664SystemV convention in a number of ways, most notably in +that XMM registers used to pass arguments are shadowed by GPRs, +and vice versa.

      + +

      On AArch64, this is identical to the normal C (aapcs) calling +convention for normal functions, but floats are passed in integer +registers to variadic functions.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case win64
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + x86VectorCall + +
      +
      +
      +
      +
      +
      +

      MSVC calling convention that passes vectors and vector aggregates +in SSE registers.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case x86VectorCall
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + hhvm + +
      +
      +
      +
      +
      +
      +

      Calling convention used by HipHop Virtual Machine (HHVM) to +perform calls to and from translation cache, and for calling PHP +functions.

      + +

      HHVM is a very relaxed convention that marks as many registers as +general-purpose as possible, including RBP which contains the first +argument, but excluding RSP and R12 which are used for the stack pointer +and return value respectively.

      + +

      This calling convention supports tail and sibling call elimination.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case hhvm
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + hhvmc + +
      +
      +
      +
      +
      +
      +

      HHVM calling convention for invoking C/C++ helpers.

      + +

      This calling convention differs from the standard c calling convention +in that the first argument is passed in RBP.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case hhvmc
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + x86Interrupt + +
      +
      +
      +
      +
      +
      +

      The calling convention for x86 hardware interrupts.

      + +

      The callee may take one or two parameters, where the 1st represents a +pointer to hardware context frame and the 2nd represents a hardware error +code. The presence of the latter depends on the interrupt vector taken.

      + +

      This convention is valid for both 32-bit and 64-bit subtargets.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case x86Interrupt
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + avrInterrupt + +
      +
      +
      +
      +
      +
      +

      Calling convention for AVR interrupt routines.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case avrInterrupt
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + avrSignal + +
      +
      +
      +
      +
      +
      +

      Calling convention used for AVR signal routines.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case avrSignal
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + avrBuiltin + +
      +
      +
      +
      +
      +
      +

      Calling convention used for special AVR rtlib functions +which have an “optimized” convention to preserve registers.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case avrBuiltin
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + amdGPUVertexShader + +
      +
      +
      +
      +
      +
      +

      Calling convention used for Mesa vertex shaders, or AMDPAL last shader +stage before rasterization (vertex shader if tessellation and geometry +are not in use, or otherwise copy shader if one is needed).

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case amdGPUVertexShader
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + amdGPUGeometryShader + +
      +
      +
      +
      +
      +
      +

      Calling convention used for Mesa/AMDPAL geometry shaders.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case amdGPUGeometryShader
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + amdGPUPixelShader + +
      +
      +
      +
      +
      +
      +

      Calling convention used for Mesa/AMDPAL pixel shaders.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case amdGPUPixelShader
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + amdGPUComputeShader + +
      +
      +
      +
      +
      +
      +

      Calling convention used for Mesa/AMDPAL compute shaders.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case amdGPUComputeShader
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + amdGPUKernel + +
      +
      +
      +
      +
      +
      +

      Calling convention for AMDGPU code object kernels.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case amdGPUKernel
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + x86RegisterCall + +
      +
      +
      +
      +
      +
      +

      Register calling convention used for parameters transfer optimization

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case x86RegisterCall
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + amdGPUHullShader + +
      +
      +
      +
      +
      +
      +

      Calling convention used for Mesa/AMDPAL hull shaders (= tessellation +control shaders).

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case amdGPUHullShader
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + msp430Builtin + +
      +
      +
      +
      +
      +
      +

      Calling convention used for special MSP430 rtlib functions +which have an “optimized” convention using additional registers.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case msp430Builtin
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + amdGPULS + +
      +
      +
      +
      +
      +
      +

      Calling convention used for AMDPAL vertex shader if tessellation is in +use.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case amdGPULS
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + amdGPUES + +
      +
      +
      +
      +
      +
      +

      Calling convention used for AMDPAL shader stage before geometry shader +if geometry is in use. So either the domain (= tessellation evaluation) +shader if tessellation is in use, or otherwise the vertex shader.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case amdGPUES
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + llvm + +
      +
      +
      +
      +
      +
      +

      Retrieves the corresponding LLVMCallConv.

      Declaration

      Swift

      -
      case x86Fastcall = 65
      +
      public var llvm: LLVMCallConv { get }
      @@ -577,8 +2015,8 @@

      Declaration

      diff --git a/docs/Enums/CodeGenOptLevel.html b/docs/Enums/CodeGenOptLevel.html index 6b4ab056..7050c575 100644 --- a/docs/Enums/CodeGenOptLevel.html +++ b/docs/Enums/CodeGenOptLevel.html @@ -1,27 +1,35 @@ - CodeGenOptLevel Enum Reference + CodeGenOptLevel Enumeration Reference + + + - +
      -

      Docs (100% documented)

      +

      LLVM 0.8 Docs (100% documented)

      +

      +

      + +
      +

      @@ -30,30 +38,93 @@
    - - -
    -
    • - + - less + less
      @@ -413,23 +651,19 @@

      Declaration

      Declaration

      Swift

      -
      case less
      +
      case less
    - - -
    -
    • - + - default + default
      @@ -440,8 +674,8 @@

      Declaration

      Optimize for fast execution as much as possible without triggering significant incremental compile time or code size growth.

      -

      The key idea is that optimizations at this level should pay for -themselves. So if an optimization increases compile time by 5% or +

      The key idea is that optimizations at this level should “pay for +themselves”. So if an optimization increases compile time by 5% or increases code size by 5% for a particular benchmark, that benchmark should also be one which sees a 5% runtime improvement. If the compile time or code size penalties happen on average across a diverse range of @@ -459,23 +693,19 @@

      Declaration

      Declaration

      Swift

      -
      case `default`
      +
      case `default`
    - - -
    -
    • @@ -503,23 +733,19 @@

      Declaration

      Declaration

      Swift

      -
      case aggressive
      +
      case aggressive
    - - -
    -
    • - + - asLLVM() + asLLVM()
      @@ -535,7 +761,7 @@

      Declaration

      Declaration

      Swift

      -
      public func asLLVM() -> LLVMCodeGenOptLevel
      +
      public func asLLVM() -> LLVMCodeGenOptLevel
      @@ -547,8 +773,8 @@

      Declaration

    diff --git a/docs/Enums/CodeModel.html b/docs/Enums/CodeModel.html index 9b0a9f0c..2bff37c6 100644 --- a/docs/Enums/CodeModel.html +++ b/docs/Enums/CodeModel.html @@ -1,27 +1,35 @@ - CodeModel Enum Reference + CodeModel Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • @@ -403,23 +641,19 @@

      Declaration

      Declaration

      Swift

      -
      case jitDefault
      +
      case jitDefault
    - - -
    -
    • - + - small + small
      @@ -447,23 +681,19 @@

      Declaration

      Declaration

      Swift

      -
      case small
      +
      case small
    - - -
    -
    • - + - kernel + kernel
      @@ -487,23 +717,19 @@

      Declaration

      Declaration

      Swift

      -
      case kernel
      +
      case kernel
    - - -
    -
    • - + - medium + medium
      @@ -530,23 +756,19 @@

      Declaration

      Declaration

      Swift

      -
      case medium
      +
      case medium
    - - -
    -
    • - + - large + large
      @@ -572,23 +794,19 @@

      Declaration

      Declaration

      Swift

      -
      case large
      +
      case large
    - - -
    -
    • - + - asLLVM() + asLLVM()
      @@ -604,7 +822,7 @@

      Declaration

      Declaration

      Swift

      -
      public func asLLVM() -> LLVMCodeModel
      +
      public func asLLVM() -> LLVMCodeModel
      @@ -616,8 +834,8 @@

      Declaration

    diff --git a/docs/Enums/CodegenFileType.html b/docs/Enums/CodegenFileType.html index 5edbca02..7f9a4e74 100644 --- a/docs/Enums/CodegenFileType.html +++ b/docs/Enums/CodegenFileType.html @@ -1,27 +1,35 @@ - CodegenFileType Enum Reference + CodegenFileType Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • - + - assembly + assembly
      @@ -396,23 +634,19 @@

      Declaration

      Declaration

      Swift

      -
      case assembly
      +
      case assembly
    - - -
    -
    • - + - bitCode + bitCode
      @@ -427,23 +661,19 @@

      Declaration

      Declaration

      Swift

      -
      case bitCode
      +
      case bitCode
    - - -
    -
    • - + - asLLVM() + asLLVM()
      @@ -459,7 +689,7 @@

      Declaration

      Declaration

      Swift

      -
      public func asLLVM() -> LLVMCodeGenFileType
      +
      public func asLLVM() -> LLVMCodeGenFileType
      @@ -471,8 +701,8 @@

      Declaration

    diff --git a/docs/docsets/.docset/Contents/Resources/Documents/Enums/IntPredicate.html b/docs/Enums/DIAttributeTypeEncoding.html similarity index 55% rename from docs/docsets/.docset/Contents/Resources/Documents/Enums/IntPredicate.html rename to docs/Enums/DIAttributeTypeEncoding.html index 63d31206..4296a1da 100644 --- a/docs/docsets/.docset/Contents/Resources/Documents/Enums/IntPredicate.html +++ b/docs/Enums/DIAttributeTypeEncoding.html @@ -1,27 +1,35 @@ - IntPredicate Enum Reference + DIAttributeTypeEncoding Enumeration Reference + + + - - + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    -
    -
    • - - - notEqual + + + boolean
      @@ -390,31 +627,26 @@

      Declaration

      -

      Yields true if the operands are unequal, false otherwise without sign -interpretation.

      +

      A true or false value.

      Declaration

      Swift

      -
      case notEqual
      +
      case boolean
    • -
    -
    -
    -
    • @@ -422,31 +654,26 @@

      Declaration

      -

      Interprets the operands as unsigned values and yields true if the first is -greater than the second.

      +

      A complex binary floating-point number.

      Declaration

      Swift

      -
      case unsignedGreaterThan
      +
      case complexFloat
    • -
    -
    -
    -
    • @@ -454,31 +681,26 @@

      Declaration

      -

      Interprets the operands as unsigned values and yields true if the first is -greater than or equal to the second.

      +

      A binary floating-point number.

      Declaration

      Swift

      -
      case unsignedGreaterThanOrEqual
      +
      case float
    • -
    -
    -
    -
    • - - - unsignedLessThan + + + signed
      @@ -486,31 +708,26 @@

      Declaration

      -

      Interprets the operands as unsigned values and yields true if the first is -less than the second.

      +

      A signed binary integer.

      Declaration

      Swift

      -
      case unsignedLessThan
      +
      case signed
    • -
    -
    -
    -
    • @@ -518,31 +735,26 @@

      Declaration

      -

      Interprets the operands as unsigned values and yields true if the first is -less than or equal to the second.

      +

      A signed character.

      Declaration

      Swift

      -
      case unsignedLessThanOrEqual
      +
      case signedChar
    • -
    -
    -
    -
    • @@ -550,31 +762,26 @@

      Declaration

      -

      Interprets the operands as signed values and yields true if the first is -greater than the second.

      +

      An unsigned binary integer.

      Declaration

      Swift

      -
      case signedGreaterThan
      +
      case unsigned
    • -
    -
    -
    -
    • @@ -582,126 +789,26 @@

      Declaration

      -

      Interprets the operands as signed values and yields true if the first is -greater than or equal to the second.

      +

      An unsigned character.

      Declaration

      Swift

      -
      case signedGreaterThanOrEqual
      +
      case unsignedChar
    • -
    -
    -
    -
      -
    • -
      - - - - signedLessThan - -
      -
      -
      -
      -
      -
      -

      Interprets the operands as signed values and yields true if the first is -less than the second.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      case signedLessThan
      - -
      -
      -
      -
      -
    • -
    -
    -
    -
      -
    • -
      - - - - signedLessThanOrEqual - -
      -
      -
      -
      -
      -
      -

      Interprets the operands as signed values and yields true if the first is -less than or equal to the second.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      case signedLessThanOrEqual
      - -
      -
      -
      -
      -
    • -
    -
    -
    -
      -
    • -
      - - - - llvm - -
      -
      -
      -
      -
      -
      -

      Retrieves the corresponding LLVMIntPredicate.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public var llvm: LLVMIntPredicate
      - -
      -
      -
      -
      -
    • -
    -
    -
    -
    • - - - eq + + + imaginaryFloat
      @@ -709,15 +816,14 @@

      Declaration

      -

      Yields true if the operands are equal, false otherwise without sign -interpretation.

      +

      An imaginary binary floating-point number.

      Declaration

      Swift

      -
      public static let eq = equal
      +
      case imaginaryFloat
      @@ -727,9 +833,9 @@

      Declaration

    • - - - ne + + + packedDecimal
      @@ -737,15 +843,14 @@

      Declaration

      -

      Yields true if the operands are unequal, false otherwise without sign -interpretation.

      +

      A packed decimal number.

      Declaration

      Swift

      -
      public static let ne = notEqual
      +
      case packedDecimal
      @@ -755,9 +860,9 @@

      Declaration

    • - - - ugt + + + numericString
      @@ -765,15 +870,14 @@

      Declaration

      -

      Interprets the operands as unsigned values and yields true if the first is -greater than the second.

      +

      A numeric string.

      Declaration

      Swift

      -
      public static let ugt = unsignedGreaterThan
      +
      case numericString
      @@ -783,9 +887,9 @@

      Declaration

    • - - - uge + + + edited
      @@ -793,15 +897,14 @@

      Declaration

      -

      Interprets the operands as unsigned values and yields true if the first is -greater than or equal to the second.

      +

      An edited string.

      Declaration

      Swift

      -
      public static let uge = unsignedGreaterThanOrEqual
      +
      case edited
      @@ -811,9 +914,9 @@

      Declaration

    • - - - ult + + + signedFixed
      @@ -821,15 +924,14 @@

      Declaration

      -

      Interprets the operands as unsigned values and yields true if the first is -less than the second.

      +

      A signed fixed-point scaled integer.

      Declaration

      Swift

      -
      public static let ult = unsignedLessThan
      +
      case signedFixed
      @@ -839,9 +941,9 @@

      Declaration

    • - - - ule + + + unsignedFixed
      @@ -849,15 +951,14 @@

      Declaration

      -

      Interprets the operands as unsigned values and yields true if the first is -less than or equal to the second.

      +

      An unsigned fixed-point scaled integer.

      Declaration

      Swift

      -
      public static let ule = unsignedLessThanOrEqual
      +
      case unsignedFixed
      @@ -867,9 +968,9 @@

      Declaration

    • - - - sgt + + + decimalFloat
      @@ -877,15 +978,14 @@

      Declaration

      -

      Interprets the operands as signed values and yields true if the first is -greater than the second.

      +

      An IEEE-754R decimal floating-point number.

      Declaration

      Swift

      -
      public static let sgt = signedGreaterThan
      +
      case decimalFloat
      @@ -895,9 +995,9 @@

      Declaration

    • - - - sge + + + utf
      @@ -905,15 +1005,14 @@

      Declaration

      -

      Interprets the operands as signed values and yields true if the first is -greater than or equal to the second.

      +

      An ISO/IEC 10646-1:1993 character.

      Declaration

      Swift

      -
      public static let sge = signedGreaterThanOrEqual
      +
      case utf
      @@ -923,9 +1022,9 @@

      Declaration

    • - - - slt + + + ucs
      @@ -933,15 +1032,14 @@

      Declaration

      -

      Interprets the operands as signed values and yields true if the first is -less than the second.

      +

      An ISO/IEC 10646-1:1993 character in UCS-4 format.

      Declaration

      Swift

      -
      public static let slt = signedLessThan
      +
      case ucs
      @@ -951,9 +1049,9 @@

      Declaration

    • - - - sle + + + ascii
      @@ -961,15 +1059,14 @@

      Declaration

      -

      Interprets the operands as signed values and yields true if the first is -less than or equal to the second.

      +

      An ISO/IEC 646:1991 character.

      Declaration

      Swift

      -
      public static let sle = signedLessThanOrEqual
      +
      case ascii
      @@ -981,8 +1078,8 @@

      Declaration

    • diff --git a/docs/Enums/DWARFEmissionKind.html b/docs/Enums/DWARFEmissionKind.html new file mode 100644 index 00000000..7ebca4d6 --- /dev/null +++ b/docs/Enums/DWARFEmissionKind.html @@ -0,0 +1,683 @@ + + + + DWARFEmissionKind Enumeration Reference + + + + + + + + + + + + + +
      +
      +

      LLVM 0.8 Docs (100% documented)

      +

      +

      + +
      +

      +
      +
      +
      + +
      +
      + +
      +
      +
      +

      DWARFEmissionKind

      +
      +
      + +
      public enum DWARFEmissionKind
      + +
      +
      +

      The amount of debug information to emit.

      + +
      +
      +
      +
        +
      • +
        + + + + none + +
        +
        +
        +
        +
        +
        +

        No debug information should be emitted.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case none
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + full + +
        +
        +
        +
        +
        +
        +

        Full debug information should be emitted.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case full
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lineTablesOnly + +
        +
        +
        +
        +
        +
        +

        Onle line tables should be emitted.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lineTablesOnly
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + +
      +
      + +
    • + diff --git a/docs/Enums/DWARFExpression.html b/docs/Enums/DWARFExpression.html new file mode 100644 index 00000000..091413fb --- /dev/null +++ b/docs/Enums/DWARFExpression.html @@ -0,0 +1,5437 @@ + + + + DWARFExpression Enumeration Reference + + + + + + + + + + + + + +
      +
      +

      LLVM 0.8 Docs (100% documented)

      +

      +

      + +
      +

      +
      +
      +
      + +
      +
      + +
      +
      +
      +

      DWARFExpression

      +
      +
      + +
      public enum DWARFExpression
      + +
      +
      +

      DWARF expressions describe how to compute a value or specify a location. +They are expressed in terms of DWARF operations that operate on a stack of +values.

      + +

      A DWARF expression is encoded as a stream of operations, each consisting of +an opcode followed by zero or more literal operands.

      + +
      +
      +
      +
      + + +
      + +

      Literals

      +

      +
      +
      +
        +
      • +
        + + + + addr(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes a single machine address value whose size is the size of an +address on the target machine.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case addr(UInt64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit0 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 0.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit0
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit1 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 1.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit1
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit2 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 2.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit2
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit3 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 3.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit3
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit4 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 4.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit4
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit5 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 5.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit5
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit6 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 6.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit6
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit7 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 7.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit7
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit8 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 8.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit8
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit9 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 9.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit9
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit10 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 10.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit10
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit11 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 11.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit11
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit12 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 12.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit12
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit13 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 13.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit13
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit14 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 14.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit14
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit15 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 15.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit15
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit16 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 16.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit16
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit17 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 17.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit17
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit18 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 18.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit18
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit19 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 19.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit19
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit20 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 20.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit20
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit21 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 21.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit21
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit22 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 22.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit22
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit23 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 23.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit23
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit24 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 24.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit24
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit25 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 25.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit25
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit26 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 26.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit26
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit27 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 27.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit27
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit28 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 28.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit28
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit29 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 29.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit29
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit30 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 30.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit30
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lit31 + +
        +
        +
        +
        +
        +
        +

        Encodes the unsigned literal value 31.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lit31
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + const1u(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes a 1-byte unsigned integer constant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case const1u(UInt8)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + const1s(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes a 1-byte signed integer constant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case const1s(Int8)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + const2u(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes a 2-byte unsigned integer constant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case const2u(UInt16)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + const2s(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes a 2-byte signed integer constant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case const2s(Int16)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + const4u(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes a 4-byte unsigned integer constant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case const4u(UInt32)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + const4s(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes a 4-byte signed integer constant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case const4s(Int32)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + const8u(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes a 8-byte unsigned integer constant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case const8u(UInt64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + const8s(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes a 8-byte signed integer constant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case const8s(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + constu(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes a little-endian base-128 unsigned integer constant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case constu(UInt64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + consts(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes a little-endian base-128 signed integer constant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case consts(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + addrx(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes an unsigned little-endian base-128 value, which is a zero-based +index into the .debug_addr section where a machine address is stored. +This index is relative to the value of the DW_AT_addr_base attribute +of the associated compilation unit.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case addrx(UInt64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + constx(_:) + +
        +
        +
        +
        +
        +
        +

        Encodes an unsigned little-endian base-128 value, which is a zero-based +index into the .debug_addr section where a constant, the size of a +machine address, is stored. This index is relative to the value of the +DW_AT_addr_base attribute of the associated compilation unit.

        + +

        This operation is provided for constants that require link-time relocation +but should not be interpreted by the consumer as a relocatable address ( +for example, offsets to thread-local storage).

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case constx(UInt64)
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      Register Values

      +

      +
      +
      +
        +
      • +
        + + + + fbreg(_:) + +
        +
        +
        +
        +
        +
        +

        Provides a signeed little-endian base-128 offset from the address +specified by the location description in the DW_AT_frame_base attribute +of the current function.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case fbreg(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg0(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 0.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg0(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg1(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 1.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg1(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg2(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 2.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg2(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg3(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 3.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg3(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg4(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 4.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg4(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg5(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 5.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg5(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg6(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 6.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg6(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg7(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 7.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg7(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg8(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 8.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg8(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg9(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 9.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg9(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg10(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 10.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg10(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg11(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 11.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg11(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg12(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 12.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg12(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg13(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 13.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg13(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg14(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 14.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg14(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg15(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 15.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg15(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg16(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 16.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg16(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg17(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 17.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg17(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg18(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 18.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg18(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg19(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 19.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg19(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg20(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 20.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg20(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg21(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 21.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg21(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg22(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 22.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg22(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg23(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 23.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg23(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg24(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 24.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg24(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg25(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 25.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg25(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg26(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 26.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg26(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg27(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 27.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg27(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg28(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 28.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg28(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg29(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 29.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg29(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg30(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 30.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg30(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + breg31(_:) + +
        +
        +
        +
        +
        +
        +

        The single operand of the breg operation provides a signed little-endian +base-128 offset from the contents of register 31.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case breg31(Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + bregx(_:_:) + +
        +
        +
        +
        +
        +
        +

        Provides the sum of two values specified by its two operands. The first +operand being a register number which is in unsigned little-endian +base-128 form. The second being an offset in signed little-endian +base-128 form.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case bregx(UInt64, Int64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + constType(_:_:_:) + +
        +
        +
        +
        +
        +
        +

        Provides an operation with three operands: The first is an unsigned +little-endian base-128 integer that represents the offset of a debugging +information entry in the current compilation unit, which must be +a base type entry that provides the type of the constant provided. +The second operand is a 1-byte unsigned integer that specifies the +size of the constant value, which is the same size as the base type +referenced by the first operand. The third operand is a sequence of bytes +of the given size that is interpreted as a value of the referenced type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case constType(DIAttributeTypeEncoding, UInt8, [UInt8])
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + regvalType(_:_:) + +
        +
        +
        +
        +
        +
        +

        Provides the contents of a given register interpreted as a value of a +given type. The first operand is an unsigned little-endian base-128 +number which identifies a register whose contents are pushed onto the +stack. The second operand is an unsigned little-endian base-128 number +that represents the offset of a debugging information entry in the current +compilation unit which must have base type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case regvalType(UInt64, DIAttributeTypeEncoding)
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      Stack Operations

      +

      +
      +
      +
        +
      • +
        + + + + dup + +
        +
        +
        +
        +
        +
        +

        Duplicates the value (including its type identifier) at the top of the +stack.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case dup
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + drop + +
        +
        +
        +
        +
        +
        +

        Pops the value (including its type identifier) at the top of the stack.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case drop
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + pick(_:) + +
        +
        +
        +
        +
        +
        +

        Provides a 1-byte index that is used to index into the stack. A copy of +stack entry at that index is pushed onto the stack.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case pick(UInt8)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + over + +
        +
        +
        +
        +
        +
        +

        Duplicates the entry currently second in the stack and pushes it onto the +stack.

        + +

        This operation is equivalent to .pick(1).

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case over
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + swap + +
        +
        +
        +
        +
        +
        +

        Swaps the top two stack entries. The entry at the top of the stack +(including its type identifier) becomes the second stack entry, and the +second entry (including its type identifier) becomes the top of the stack.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case swap
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + rot + +
        +
        +
        +
        +
        +
        +

        Rotates the first three stack entries. The entry at the top of the stack +(including its type identifier) becomes the third stack entry, the second +stack entry (including its type identifier) becomes the top of the stack, +and the third entry (including its type identifier) becomes the second +entry.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case rot
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + deref + +
        +
        +
        +
        +
        +
        +

        Pops the top stack entry and treats it as an address.

        + +

        The popped value must have an integral type. The value retrieved from +that address is pushed, and has the generic type. The size of the data +retrieved from the dereferenced address is the size of an address on the +target machine.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case deref
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + derefSize(_:) + +
        +
        +
        +
        +
        +
        +

        Pops the top stack entry and treats it as an address.

        + +

        The popped value must have an integral type. The value retrieved from +that address is pushed, and has the generic type. The size of the data +retrieved from the dereferenced address is specified by the +operand, whose value is a 1-byte unsigned integral constant. The data +retrieved is zero-extended to the size of an address on the target machine +before being pushed onto the expression stack.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case derefSize(UInt8)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + derefType(_:_:) + +
        +
        +
        +
        +
        +
        +

        Pops the top stack entry and treats it as an address.

        + +

        The popped value must have an integral type. The size of the data +retrieved from the dereferenced address is specified by the first +operand, whose value is a 1-byte unsigned integral constant. The data +retrieved is zero-extended to the size of an address on the target machine +before being pushed onto the expression stack. The second operand is an +unsigned little-endian base-128 integer that represents the offset of a +debugging information entry in the current compilation unit which must +have a base type entry that provides the type of the data pushed.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case derefType(UInt8, UInt64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + xderef + +
        +
        +
        +
        +
        +
        +

        Provides an extended dereference mechanism.

        + +

        The entry at the top of the stack is treated as an address. The second +stack entry is treated as an “address space identifier” for those +architectures that support multiple address spaces. Both of these +entries must have integral type identifiers.

        + +

        The top two stack elements are popped, and a data item is retrieved +through an implementation-defined address calculation and pushed as the +new stack top together with the generic type identifier. The size of the +data retrieved from the dereferenced address is the size of the +generic type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case xderef
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + xderefSize(_:) + +
        +
        +
        +
        +
        +
        +

        Provides an extended dereference mechanism.

        + +

        The entry at the top of the stack is treated as an address. The second +stack entry is treated as an “address space identifier” for those +architectures that support multiple address spaces. Both of these +entries must have integral type identifiers.

        + +

        The top two stack elements are popped, and a data item is retrieved +through an implementation-defined address calculation and pushed as the +new stack top together with the generic type identifier. The size of the +data retrieved from the dereferenced address is specified by the +operand, whose value is a 1-byte unsigned integral constant. The data +retrieved is zero-extended to the size of an address on the target machine +before being pushed onto the expression stack.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case xderefSize(UInt8)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + xderefType(_:_:) + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack entries, treats them as an address and an address +space identifier, and pushes the value retrieved. +The size of the data retrieved from the dereferenced address is specified +by the first operand, whose value is a 1-byte unsigned integral constant. +The data retrieved is zero-extended to the size of an address on the +target machine before being pushed onto the expression stack. The second +operand is an unsigned little-endian base-128 integer that represents the +offset of a debugging information entry in the current compilation unit, +which must have base type that provides the type of the data pushed.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case xderefType(UInt8, UInt64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + pushObjectAddress + +
        +
        +
        +
        +
        +
        +

        Pushes the address of the object currently being evaluated as part of +evaluationo of a user-presented expression. The object may correspond +to an indepdendent variable deescribed by its own debugging information +entry or it may be a component of an array, structure, or class whose +address has been dynamically determined by an earlier step during +user expression evaluation.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case pushObjectAddress
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + formTLSAddress + +
        +
        +
        +
        +
        +
        +

        Pops a value from the stack, which must have an integral type identifier, +translates this value into an address in the thread-local storage for a +thread, and pushes the addreess onto the stack together with the generic +type identifier. The meaning of the value on the top of the stack prior +to this operation is defined by the run-time environment. If the run-time +environment supports multiple thread-local storage blocks for a single +thread, then the block corresponding to the executable or shared library +containing this DWARF expreession is used.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case formTLSAddress
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + callFrameCFA + +
        +
        +
        +
        +
        +
        +

        Pushes the value of the Canonical Frame Address (CFA), obtained from the +Call Frame Information.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case callFrameCFA
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      Arithmetic and Logical Operations

      +

      +
      +
      +
        +
      • +
        + + + + abs + +
        +
        +
        +
        +
        +
        +

        Pops the top stack entry, interprets it as a signed value and pushes its +absolute value. If the absolute value cannot be represented, the result +is undefined.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case abs
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + and + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack values, performs a bitwise and operation on the +two, and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case and
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + div + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack values, divides the former second entry by the +former top of the stack using signed division, and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case div
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + minus + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack values, subtracts the former second entry by the +former top of the stack, and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case minus
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + mod + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack values, performs a modulo operation on the +two, and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case mod
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + mul + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack values, multiplies the former second entry by the +former top of the stack, and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case mul
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + neg + +
        +
        +
        +
        +
        +
        +

        Pops the top stack entry, interprets it as a signed value, and pushes its +negation. If the negation cannot be represented, the result is undefined.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case neg
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + not + +
        +
        +
        +
        +
        +
        +

        Pops the top stack entry, and pushes its bitwise complement.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case not
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + or + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack entries, performs a bitwise or operation on the +two, and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case or
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + plus + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack entries, adds them together, and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case plus
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + plus_uconst(_:) + +
        +
        +
        +
        +
        +
        +

        Pops the top stack entry, adds it to the unsigned little-endian base-128 +constant operand interpreted as the same type as the operand popped from +the top of the stack and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case plus_uconst(UInt64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + shl + +
        +
        +
        +
        +
        +
        +

        Pops the top twoo stack entries, shifts the former second entry left +(filling with zero bits) by the number of bits specified by the former +top of the stack, and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case shl
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + shr + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack entries, shifts the former second entry right +logically (filling with zero bits) by the number of bits specified by +the former top of the stack, and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case shr
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + shra + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack entries, shifts the former second entry right +arithmetically (divides the magnitude by 2, keeps the same sign for the +result) by the number of bits specified by the former top of the stack, +and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case shra
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + xor + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack entries, performs a bitwise exclusive-or operation +on the two, and pushes the result.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case xor
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      Control Flow Operations

      +

      +
      +
      +
        +
      • +
        + + + + eq + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack values, which must have the same type, either +the base type or the generic type, compares them using the = relational +operator, and pushes the constant 1 onto the stack if the result is +true, else pushes the constnat value 0 if the result is false.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case eq
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + ge + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack values, which must have the same type, either +the base type or the generic type, compares them using the >= relational +operator, and pushes the constant 1 onto the stack if the result is +true, else pushes the constnat value 0 if the result is false.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case ge
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + gt + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack values, which must have the same type, either +the base type or the generic type, compares them using the > relational +operator, and pushes the constant 1 onto the stack if the result is +true, else pushes the constnat value 0 if the result is false.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case gt
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + le + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack values, which must have the same type, either +the base type or the generic type, compares them using the <= relational +operator, and pushes the constant 1 onto the stack if the result is +true, else pushes the constnat value 0 if the result is false.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case le
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lt + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack values, which must have the same type, either +the base type or the generic type, compares them using the < relational +operator, and pushes the constant 1 onto the stack if the result is +true, else pushes the constnat value 0 if the result is false.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lt
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + ne + +
        +
        +
        +
        +
        +
        +

        Pops the top two stack values, which must have the same type, either +the base type or the generic type, compares them using the != relational +operator, and pushes the constant 1 onto the stack if the result is +true, else pushes the constnat value 0 if the result is false.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case ne
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + skip(_:) + +
        +
        +
        +
        +
        +
        +

        Unconditionally branches forward or backward by the number of bytes +specified in its operand.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case skip(Int16)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + bra(_:) + +
        +
        +
        +
        +
        +
        +

        Conditionally branches forward or backward by the number of bytes +specified in its operand according to the value at the top of the stack. +The top of the stack is popped, and if it is non-zero then the branch is +performed.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case bra(Int16)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + call2(_:) + +
        +
        +
        +
        +
        +
        +

        Performs a DWARF procedure call during the evaluation of a DWARF +expression or location description. The operand is the 2-byte unsigned +offset of a debugging information entry in the current compilation unit.

        + +

        For references from one executable or shared object file to another, +the relocation must be performed by the consumer.

        + +

        This operation transfers control of DWARF expression evaluation to the +DW_AT_location attribute of the referenced debugging information entry. +If there is no such attribute, then there is no effect. Execution +returns to the point following the call when the end of the attribute +is reached.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case call2(UInt16)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + call4(_:) + +
        +
        +
        +
        +
        +
        +

        Performs a DWARF procedure call during the evaluation of a DWARF +expression or location description. The operand is the 4-byte unsigned +offset of a debugging information entry in the current compilation unit.

        + +

        For references from one executable or shared object file to another, +the relocation must be performed by the consumer.

        + +

        This operation transfers control of DWARF expression evaluation to the +DW_AT_location attribute of the referenced debugging information entry. +If there is no such attribute, then there is no effect. Execution +returns to the point following the call when the end of the attribute +is reached.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case call4(UInt32)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + callRef(_:) + +
        +
        +
        +
        +
        +
        +

        Performs a DWARF procedure call during the evaluation of a DWARF +expression or location description. The operand is used as the offset of +a debugging information entry in a .debug_info section which may be +contained in an executable or shared object file rather than that +containing the operator.

        + +

        For references from one executable or shared object file to another, +the relocation must be performed by the consumer.

        + +

        This operation transfers control of DWARF expression evaluation to the +DW_AT_location attribute of the referenced debugging information entry. +If there is no such attribute, then there is no effect. Execution +returns to the point following the call when the end of the attribute +is reached.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case callRef(UInt64)
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      Type Conversions

      +

      +
      +
      +
        +
      • +
        + + + + convert(_:) + +
        +
        +
        +
        +
        +
        +

        Pops the top stack entry, converts it to a different type, then pushes the +result.

        + +

        The operand is an unsigned little-endian base-128 integer that represents +the offset of a debugging information entry in the current compilation +unit, or value 0 which represents the generic type. If the operand is +non-zero, the referenced entry must be a base type entry that provides the +type to which the value is converted.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case convert(UInt64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reinterpret(_:) + +
        +
        +
        +
        +
        +
        +

        Pops the top stack entry, reinterprets the bits in its value as a value of +a different type, then pushes the result.

        + +

        The operand is an unsigned little-endian base-128 integer that represents +the offset of a debugging information entry in the current compilation +unit, or value 0 which represents the generic type. If the operand is +non-zero, the referenced entry must be a base type entry that provides the +type to which the value is converted.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reinterpret(UInt64)
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      Special Operations

      +

      +
      +
      +
        +
      • +
        + + + + nop + +
        +
        +
        +
        +
        +
        +

        This operation has no effect on the location stack or any of its values.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case nop
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + entryValue(_:_:) + +
        +
        +
        +
        +
        +
        +

        Pushes the value that the described location held upon entering the +current subprogram. The first operand is an unsigned little-endian +base-128 number expressing the length of the second operand in bytes. The +second operand is a block containing a DWARF expression or a register +location description.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        indirect case entryValue(UInt64, DWARFExpression)
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      Location Descriptions

      +

      +
      +
      +
        +
      • +
        + + + + reg0 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 0.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg0
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg1 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 1.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg1
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg2 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 2.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg2
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg3 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 3.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg3
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg4 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 4.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg4
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg5 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 5.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg5
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg6 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 6.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg6
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg7 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 7.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg7
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg8 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 8.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg8
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg9 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 9.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg9
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg10 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 10.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg10
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg11 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 11.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg11
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg12 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 12.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg12
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg13 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 13.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg13
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg14 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 14.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg14
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg15 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 15.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg15
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg16 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 16.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg16
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg17 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 17.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg17
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg18 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 18.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg18
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg19 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 19.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg19
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg20 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 20.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg20
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg21 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 21.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg21
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg22 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 22.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg22
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg23 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 23.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg23
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg24 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 24.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg24
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg25 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 25.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg25
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg26 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 26.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg26
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg27 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 27.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg27
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg28 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 28.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg28
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg29 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 29.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg29
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg30 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 30.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg30
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + reg31 + +
        +
        +
        +
        +
        +
        +

        Encodes the name of the register numbered 31.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case reg31
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + regx(_:) + +
        +
        +
        +
        +
        +
        +

        Contains a single unsigned little-endian base-128 literal operand that +encodes the name of a register.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case regx(UInt64)
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      Implicit Location Descriptionos

      +

      +
      +
      +
        +
      • +
        + + + + implicitValue(_:_:) + +
        +
        +
        +
        +
        +
        +

        Specifies an immediate value using two operands: an unsigned little-endian +base-128 length, followed by a sequence of bytes of the given length that +contain the value.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case implicitValue(UInt64, [UInt8])
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + stackValue + +
        +
        +
        +
        +
        +
        +

        Specifies that the object does not exist in memory, but its value is +nonetheless known and is at the top of the DWARF expression stack. In +this form of location description, the DWARF expression represents the +actual value of the object, rather than its location.

        + +

        stackValue acts as an expression terminator.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case stackValue
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      Composite Location Descriptions

      +

      +
      +
      +
        +
      • +
        + + + + piece(_:) + +
        +
        +
        +
        +
        +
        +

        Takes a single operand in little-endian base-128 form. This operand +describes the size in bytes of the piece of the object referenced by the +preceding simple location description. If the piece is located in a +register, but does not occupy the entire register, the placement of +the piece within that register is defined by the ABI.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case piece(UInt64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + bitPiece(_:_:) + +
        +
        +
        +
        +
        +
        +

        Takes two operands, an unsigned little-endian base-128 form number that +gives the size in bits of the piece. The second is an unsigned little- +endian base-128 number that gives the offset in bits from the location +defined by the preceding DWARF location description.

        + +

        bitPiece is used instead of piece when the piece to be assembled into +a value or assigned to is not byte-sized or is not at the start of a +register or addressable unit of memory.

        + +

        Interpretation of the offset depends on the location description. If the +location description is empty, the offset doesn’t matter and the +bitPiece operation describes a piece consisting of the given number of +bits whose values are undefined. If the location is a register, the offset +is from the least significant bit end of the register. If the location is +a memory address, the bitPiece operation describes a sequence of bits +relative to the location whose address is on the top of the DWARF stack +using the bit numbering and direction conventions that are appropriate to +the current language on the target system. If the location is any implicit +value or stack value, the bitPiece operation describes a sequence of +bits using the least significant bits of that value.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case bitPiece(UInt64, UInt64)
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + implicitPointer(_:_:) + +
        +
        +
        +
        +
        +
        +

        Specifies that the object is a pointer that cannot be represented as a +real pointer, even though the value it would point to can be described.

        + +

        In this form of location description, the DWARF expression refers to a +debugging information entry that represents the actual value of the object +to which the pointer would point. Thus, a consumer of the debug +information would be able to show the value of the dereferenced pointer, +even when it cannot show the value of the pointer itself.

        + +

        The first operand is used as the offset of a debugging information entry +in a .debug_info section, which may be contained in an executable or +shared object file other than that containing the operator.

        + +

        For references from one executable or shared object file to another, the +relocation must be performed by the consumer.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case implicitPointer(UInt64, Int64)
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + +
      +
      + +
    • + diff --git a/docs/Enums/DWARFSourceLanguage.html b/docs/Enums/DWARFSourceLanguage.html new file mode 100644 index 00000000..0196cdcf --- /dev/null +++ b/docs/Enums/DWARFSourceLanguage.html @@ -0,0 +1,1695 @@ + + + + DWARFSourceLanguage Enumeration Reference + + + + + + + + + + + + + +
      +
      +

      LLVM 0.8 Docs (100% documented)

      +

      +

      + +
      +

      +
      +
      +
      + +
      +
      + +
      +
      +
      +

      DWARFSourceLanguage

      +
      +
      + +
      public enum DWARFSourceLanguage
      + +
      +
      +

      Source languages known to DWARF.

      + +
      +
      +
      +
        +
      • +
        + + + + ada83 + +
        +
        +
        +
        +
        +
        +

        ISO Ada:1983

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case ada83
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + ada95 + +
        +
        +
        +
        +
        +
        +

        ISO Ada:1995

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case ada95
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + bliss + +
        +
        +
        +
        +
        +
        +

        BLISS

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case bliss
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + c + +
        +
        +
        +
        +
        +
        +

        Non-standardized C, e.g. K&R C.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case c
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + c89 + +
        +
        +
        +
        +
        +
        +

        ISO C:1989.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case c89
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + c99 + +
        +
        +
        +
        +
        +
        +

        ISO C:1999.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case c99
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + c11 + +
        +
        +
        +
        +
        +
        +

        ISO C:2011

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case c11
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + cPlusPlus + +
        +
        +
        +
        +
        +
        +

        ISO C++90

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case cPlusPlus
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + cPlusPlus03 + +
        +
        +
        +
        +
        +
        +

        ISO C++03

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case cPlusPlus03
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + cPlusPlus11 + +
        +
        +
        +
        +
        +
        +

        ISO C++11

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case cPlusPlus11
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + cPlusPlus14 + +
        +
        +
        +
        +
        +
        +

        ISO C++14

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case cPlusPlus14
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + cobol74 + +
        +
        +
        +
        +
        +
        +

        ISO COBOL:1974

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case cobol74
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + cobol85 + +
        +
        +
        +
        +
        +
        +

        ISO COBOL:1985

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case cobol85
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + d + +
        +
        +
        +
        +
        +
        +

        C

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case d
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + dylan + +
        +
        +
        +
        +
        +
        +

        Dylan

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case dylan
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + fortran77 + +
        +
        +
        +
        +
        +
        +

        ISO FORTRAN:1977

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case fortran77
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + fortran90 + +
        +
        +
        +
        +
        +
        +

        ISO Fortran:1990

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case fortran90
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + fortran95 + +
        +
        +
        +
        +
        +
        +

        ISO Fortran:1995

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case fortran95
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + fortran03 + +
        +
        +
        +
        +
        +
        +

        ISO Fortran:2004

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case fortran03
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + fortran08 + +
        +
        +
        +
        +
        +
        +

        ISO Fortran:2010

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case fortran08
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + go + +
        +
        +
        +
        +
        +
        +

        Go

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case go
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + haskell + +
        +
        +
        +
        +
        +
        +

        Haskell

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case haskell
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + java + +
        +
        +
        +
        +
        +
        +

        Java

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case java
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + julia + +
        +
        +
        +
        +
        +
        +

        Julia

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case julia
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + modula2 + +
        +
        +
        +
        +
        +
        +

        ISO Modula-2:1996

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case modula2
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + modula3 + +
        +
        +
        +
        +
        +
        +

        Module-3

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case modula3
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + objectiveC + +
        +
        +
        +
        +
        +
        +

        Objective-C

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case objectiveC
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + objectiveCPlusPlus + +
        +
        +
        +
        +
        +
        +

        Objective-C++

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case objectiveCPlusPlus
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + ocaml + +
        +
        +
        +
        +
        +
        +

        OCaml

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case ocaml
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + openCL + +
        +
        +
        +
        +
        +
        +

        OpenCL

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case openCL
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + pascal83 + +
        +
        +
        +
        +
        +
        +

        ISO Pascal:1983

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case pascal83
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + pli + +
        +
        +
        +
        +
        +
        +

        ANSI PL/I:1976

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case pli
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + python + +
        +
        +
        +
        +
        +
        +

        Python

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case python
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + renderScript + +
        +
        +
        +
        +
        +
        +

        RenderScript Kernel Language

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case renderScript
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + rust + +
        +
        +
        +
        +
        +
        +

        Rust

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case rust
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + swift + +
        +
        +
        +
        +
        +
        +

        Swift

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case swift
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + upc + +
        +
        +
        +
        +
        +
        +

        Unified Parallel C

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case upc
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      Vendor Extensions

      +

      +
      +
      +
        +
      • +
        + + + + mipsAssembler + +
        +
        +
        +
        +
        +
        +

        MIPS Assembler

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case mipsAssembler
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + googleRenderScript + +
        +
        +
        +
        +
        +
        +

        Google RenderScript Kernel Language

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case googleRenderScript
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + borlandDelphi + +
        +
        +
        +
        +
        +
        +

        Borland Delphi

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case borlandDelphi
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + +
      +
      + +
    • + diff --git a/docs/Enums/DWARFTag.html b/docs/Enums/DWARFTag.html new file mode 100644 index 00000000..cd36a63f --- /dev/null +++ b/docs/Enums/DWARFTag.html @@ -0,0 +1,2907 @@ + + + + DWARFTag Enumeration Reference + + + + + + + + + + + + + +
      +
      +

      LLVM 0.8 Docs (100% documented)

      +

      +

      + +
      +

      +
      +
      +
      + +
      +
      + +
      +
      +
      +

      DWARFTag

      +
      +
      + +
      public enum DWARFTag : UInt32
      + +
      +
      +

      Enumerates the supported identifying tags for corresponding DWARF +Debugging Information Entries (DIEs) known to LLVM.

      + +
      +
      +
      +
        +
      • +
        + + + + arrayType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an array type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case arrayType = 0x0001
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + classType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a class type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case classType = 0x0002
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + entryPoint + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an alternate entry point.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case entryPoint = 0x0003
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + enumerationType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an enumeration type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case enumerationType = 0x0004
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + formalParameter + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a formal parameter of a parameter list.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case formalParameter = 0x0005
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + importedDeclaration + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an imported declaration.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case importedDeclaration = 0x0008
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + label + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a label in the source; the +target of one or more go to statements.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case label = 0x000a
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + lexicalBlock + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a lexical block in the source (usually for +C-like languages).

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case lexicalBlock = 0x000b
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + member + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a data member.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case member = 0x000d
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + pointerType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a pointer type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case pointerType = 0x000f
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + referenceType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a reference type

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case referenceType = 0x0010
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + compileUnit + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a complete compilation unit.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case compileUnit = 0x0011
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + stringType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a string type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case stringType = 0x0012
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + structureType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a structure type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case structureType = 0x0013
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + subroutineType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a subroutine type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case subroutineType = 0x0015
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + typedef + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a typedef declaration.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case typedef = 0x0016
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + unionType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a union type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case unionType = 0x0017
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + unspecifiedParameters + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an unspecified parameter list. Can also be used +to identify vararg parameter lists.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case unspecifiedParameters = 0x0018
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + variant + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a variant record.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case variant = 0x0019
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + commonBlock + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a Fortran common block.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case commonBlock = 0x001a
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + commonInclusion + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a Fortran common inclusion.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case commonInclusion = 0x001b
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + inheritance + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an inheritance clause.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case inheritance = 0x001c
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + inlinedSubroutine + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an inlined subroutine.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case inlinedSubroutine = 0x001d
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + module + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a module.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case module = 0x001e
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + ptrToMemberType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a pointer to a data member.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case ptrToMemberType = 0x001f
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + setType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a set type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case setType = 0x0020
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + subrangeType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a subrange type describing the +dimensions of an array.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case subrangeType = 0x0021
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + withStmt + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for Pascal and Modula-2’s with statements.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case withStmt = 0x0022
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + accessDeclaration + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an access declaration.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case accessDeclaration = 0x0023
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + baseType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a a base type: a type that is not defined in terms +of metadata for other data types.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case baseType = 0x0024
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + catchBlock + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for the catch block in a try-catch statement.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case catchBlock = 0x0025
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + constType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a constant type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case constType = 0x0026
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + constant + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a constant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case constant = 0x0027
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + enumerator + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an enumerator.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case enumerator = 0x0028
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + fileType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a file.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case fileType = 0x0029
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + friend + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a C++ friend declaration.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case friend = 0x002a
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + namelist + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a Fortran 90 namelist.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case namelist = 0x002b
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + namelistItem + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an item in a Fortran 90 namelist.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case namelistItem = 0x002c
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + packedType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an Ada or Pascal packed type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case packedType = 0x002d
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + subprogram + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a subprogram.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case subprogram = 0x002e
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + templateTypeParameter + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a template type parameter.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case templateTypeParameter = 0x002f
        + +
        +
        +
        +
        +
      • +
      • + +
        +
        +
        +
        +
        +

        Identifies metadata for a template value parameter.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case templateValueParameter = 0x0030
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + thrownType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for the thrown type from a subroutine.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case thrownType = 0x0031
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + tryBlock + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for the try block in a try-catch statement.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case tryBlock = 0x0032
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + variantPart + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a part of a variant record.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case variantPart = 0x0033
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + variable + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a variable.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case variable = 0x0034
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + volatileType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a volatile-qualified type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case volatileType = 0x0035
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      New in DWARF v3

      +

      +
      +
      +
        +
      • +
        + + + + dwarfProcedure + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a DWARF procedure.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case dwarfProcedure = 0x0036
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + restrictType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a restrict-qualified type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case restrictType = 0x0037
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + interfaceType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a Java interface type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case interfaceType = 0x0038
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + namespace + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a namespace.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case namespace = 0x0039
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + importedModule + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an imported module.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case importedModule = 0x003a
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + unspecifiedType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an unspecified type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case unspecifiedType = 0x003b
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + partialUnit + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a portion of an object file.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case partialUnit = 0x003c
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + importedUnit + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an imported compilation unit.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case importedUnit = 0x003d
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + condition + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a COBOL “level-88” condition that associates a +data item, called the conditional variable, with a set of one or more +constant values and/or value ranges.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case condition = 0x003f
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + sharedType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a UPC shared-qualified type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case sharedType = 0x0040
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      New in DWARF v4

      +

      +
      +
      +
        +
      • +
        + + + + typeUnit + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a single type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case typeUnit = 0x0041
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + rvalueReferenceType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an rvalue-reference-qualified type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case rvalueReferenceType = 0x0042
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + templateAlias + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a template alias.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case templateAlias = 0x0043
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      New in DWARF v5

      +

      +
      +
      +
        +
      • +
        + + + + coarrayType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a Fortran “coarray” - an array whose elements +are located in different processes rather than in the memory of one +process.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case coarrayType = 0x0044
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + genericSubrange + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a generic subrange. This is useful for arrays of +dynamic size in C and Fortran.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case genericSubrange = 0x0045
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + dynamicType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a dynamic type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case dynamicType = 0x0046
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + atomicType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an atomic type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case atomicType = 0x0047
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + callSite + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a call site.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case callSite = 0x0048
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + callSiteParameter + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a parameter at a call site.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case callSiteParameter = 0x0049
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + skeletonUnit + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for the “skeleton” compilation unit in a split DWARF +object file.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case skeletonUnit = 0x004a
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + immutableType + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an immutable type.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case immutableType = 0x004b
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + + +
      + +

      Vendor extensions

      +

      +
      +
      +
        +
      • +
        + + + + mipsLoop + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a MIPS loop.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case mipsLoop = 0x4081
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + formatLabel + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a format label.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case formatLabel = 0x4101
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + functionTemplate + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a function template.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case functionTemplate = 0x4102
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + classTemplate + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a class template.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case classTemplate = 0x4103
        + +
        +
        +
        +
        +
      • +
      • + +
        +
        +
        +
        +
        +

        Identifies metadata for a template template parameter.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case gnuTemplateTemplateParam = 0x4106
        + +
        +
        +
        +
        +
      • +
      • + +
        +
        +
        +
        +
        +

        Identifies metadata for a template parameter pack.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case gnuTemplateParameterPack = 0x4107
        + +
        +
        +
        +
        +
      • +
      • + +
        +
        +
        +
        +
        +

        Identifies metadata for a formal parameter pack.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case gnuFormalParameterPack = 0x4108
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + gnuCallSite + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a call site.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case gnuCallSite = 0x4109
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + gnuCallSiteParameter + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for a call site parameter.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case gnuCallSiteParameter = 0x410a
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + applyProperty + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an Objective-C property.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case applyProperty = 0x4200
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + borlandProperty + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an Borland Delphi property.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case borlandProperty = 0xb000
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + borlandDelphiString + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an Borland Delphi property.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case borlandDelphiString = 0xb001
        + +
        +
        +
        +
        +
      • +
      • + +
        +
        +
        +
        +
        +

        Identifies metadata for an Borland Delphi dynamic array.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case borlandDelphiDynamicArray = 0xb002
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + borlandDelphiSet + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an Borland Delphi set.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case borlandDelphiSet = 0xb003
        + +
        +
        +
        +
        +
      • +
      • +
        + + + + borlandDelphiVariant + +
        +
        +
        +
        +
        +
        +

        Identifies metadata for an Borland Delphi variant.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        case borlandDelphiVariant = 0xb004
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + +
      +
      + +
    • + diff --git a/docs/Enums/FunctionPass.html b/docs/Enums/FunctionPass.html index af7e4f8c..03158977 100644 --- a/docs/Enums/FunctionPass.html +++ b/docs/Enums/FunctionPass.html @@ -1,7 +1,7 @@ - FunctionPass Enum Reference + FunctionPass Enumeration Reference @@ -11,17 +11,17 @@ - +
      -

      Docs (100% documented)

      +

      LLVM Docs (100% documented)

      @@ -30,27 +30,69 @@
    • -
    -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    • @@ -525,23 +667,19 @@

      Declaration

      Declaration

      Swift

      -
      case scalarizer
      +
      case scalarizer
    - - -
    -
    - - -
    -
    • - + - gvn + gvn
      @@ -589,23 +723,19 @@

      Declaration

      Declaration

      Swift

      -
      case gvn
      +
      case gvn
    - - -
    -
    - - -
    -
    - - -
    -
    • @@ -696,23 +818,19 @@

      Declaration

      Declaration

      Swift

      -
      case jumpThreading
      +
      case jumpThreading
    - - -
    -
    • - + - licm + licm
      @@ -727,23 +845,19 @@

      Declaration

      Declaration

      Swift

      -
      case licm
      +
      case licm
    - - -
    -
    • @@ -758,23 +872,19 @@

      Declaration

      Declaration

      Swift

      -
      case loopDeletion
      +
      case loopDeletion
    - - -
    -
    • @@ -789,23 +899,19 @@

      Declaration

      Declaration

      Swift

      -
      case loopIdiom
      +
      case loopIdiom
    - - -
    -
    • @@ -820,23 +926,19 @@

      Declaration

      Declaration

      Swift

      -
      case loopRotate
      +
      case loopRotate
    - - -
    -
    • @@ -851,23 +953,19 @@

      Declaration

      Declaration

      Swift

      -
      case loopReroll
      +
      case loopReroll
    - - -
    -
    • @@ -882,23 +980,46 @@

      Declaration

      Declaration

      Swift

      -
      case loopUnroll
      +
      case loopUnroll
      + +
      +
      + +
    + +
  • +
    + + + + loopUnrollAndJam + +
    +
    +
    +
    +
    +
    +

    This pass is a simple loop unroll-and-jam pass.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case loopUnrollAndJam
  • - - -
    -
    • @@ -913,23 +1034,47 @@

      Declaration

      Declaration

      Swift

      -
      case loopUnswitch
      +
      case loopUnswitch
      + +
      +
      + +
    + +
  • +
    + + + + lowerAtomic + +
    +
    +
    +
    +
    +
    +

    This pass lowers atomic intrinsics to non-atomic form for use in a known +non-preemptible environment.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case lowerAtomic
  • - - -
    -
    • @@ -945,23 +1090,19 @@

      Declaration

      Declaration

      Swift

      -
      case memCpyOpt
      +
      case memCpyOpt
    - - -
    -
    - - -
    -
    • @@ -1008,23 +1145,19 @@

      Declaration

      Declaration

      Swift

      -
      case lowerSwitch
      +
      case lowerSwitch
    - - -
    -
    - - -
    -
    • @@ -1078,7 +1207,7 @@

      Declaration

      is designed to promote better constant propagation, GCSE, LICM, PRE, etc.

      For example:

      -
      4 + (x + 5)  ->  x + (4 + 5)
      +
      4 + (x + 5)  ->  x + (4 + 5)
       
      @@ -1086,23 +1215,19 @@

      Declaration

      Declaration

      Swift

      -
      case reassociate
      +
      case reassociate
    - - -
    -
    • - + - sccp + sccp
      @@ -1117,23 +1242,19 @@

      Declaration

      Declaration

      Swift

      -
      case sccp
      +
      case sccp
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    - -
    -
    -
    - - -
    -
    • - + - earlyCSE + earlyCSE
      @@ -1367,23 +1460,19 @@

      Declaration

      Declaration

      Swift

      -
      case earlyCSE
      +
      case earlyCSE
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    • +
      +
      +
      +
      +
      +

      This pass is used to ensure that functions have at most one return +instruction in them. Additionally, it keeps track of which node is +the new exit node of the CFG.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case unifyFunctionExitNodes
      + +
      +
      +
      +
      +
    • +
    • +
      + + - verifier + verifier
      @@ -1523,23 +1625,19 @@

      Declaration

      Declaration

      Swift

      -
      case verifier
      +
      case verifier
    - - -
    -
    • @@ -1554,23 +1652,19 @@

      Declaration

      Declaration

      Swift

      -
      case alwaysInliner
      +
      case alwaysInliner
    - - -
    -
    - - -
    -
    • @@ -1620,23 +1710,19 @@

      Declaration

      Declaration

      Swift

      -
      case constantMerge
      +
      case constantMerge
    - - -
    -
    - - -
    -
    • @@ -1685,23 +1767,19 @@

      Declaration

      Declaration

      Swift

      -
      case functionAttrs
      +
      case functionAttrs
    - - -
    -
    - - -
    -
    • @@ -1748,23 +1822,19 @@

      Declaration

      Declaration

      Swift

      -
      case globalDCE
      +
      case globalDCE
    - - -
    -
    - - -
    -
    - - -
    -
    • - + - ipscc + ipscc
      @@ -1845,23 +1907,19 @@

      Declaration

      Declaration

      Swift

      -
      case ipscc
      +
      case ipscc
    - - -
    -
    • - + - pruneEH + pruneEH
      @@ -1877,23 +1935,19 @@

      Declaration

      Declaration

      Swift

      -
      case pruneEH
      +
      case pruneEH
    - - -
    -
    - - -
    -
    • @@ -1940,7 +1990,63 @@

      Declaration

      Declaration

      Swift

      -
      case stripSymbols
      +
      case stripSymbols
      + +
      +
      + +
    + +
  • +
    + + + + loopVectorize + +
    +
    +
    +
    +
    +
    +

    Performs a loop vectorization pass to widen instructions in loops to +operate on multiple consecutive iterations.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case loopVectorize
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + slpVectorize + +
    +
    +
    +
    +
    +
    +

    This pass performs a superword-level parallelism pass to combine +similar independent instructions into vector instructions.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    case slpVectorize
    @@ -1952,8 +2058,8 @@

    Declaration

    diff --git a/docs/docsets/.docset/Contents/Resources/Documents/Enums/RealPredicate.html b/docs/Enums/IRMetadataKind.html similarity index 56% rename from docs/docsets/.docset/Contents/Resources/Documents/Enums/RealPredicate.html rename to docs/Enums/IRMetadataKind.html index 63546284..8358598a 100644 --- a/docs/docsets/.docset/Contents/Resources/Documents/Enums/RealPredicate.html +++ b/docs/Enums/IRMetadataKind.html @@ -1,27 +1,35 @@ - RealPredicate Enum Reference + IRMetadataKind Enumeration Reference + + + - - + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
  • - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    • -
      -
      -
      -
      -
      -

      Interprets the operands as signed values and yields true if the first is -less than or equal to the second.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      case signedLessThanOrEqual
      - -
      -
      -
      -
      -
    • -
    -
    -
    -
      -
    • -
      - - - - llvm - -
      -
      -
      -
      -
      -
      -

      Retrieves the corresponding LLVMIntPredicate.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public var llvm: LLVMIntPredicate
      - -
      -
      -
      -
      -
    • -
    -
    -
    -
      -
    • -
      - - - - eq - -
      -
      -
      -
      -
      -
      -

      Yields true if the operands are equal, false otherwise without sign -interpretation.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public static let eq = equal
      - -
      -
      -
      -
      -
    • -
    • -
      - - - - ne - -
      -
      -
      -
      -
      -
      -

      Yields true if the operands are unequal, false otherwise without sign -interpretation.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public static let ne = notEqual
      - -
      -
      -
      -
      -
    • -
    • -
      - - - - ugt - -
      -
      -
      -
      -
      -
      -

      Interprets the operands as unsigned values and yields true if the first is -greater than the second.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public static let ugt = unsignedGreaterThan
      - -
      -
      -
      -
      -
    • -
    • -
      - - - - uge - -
      -
      -
      -
      -
      -
      -

      Interprets the operands as unsigned values and yields true if the first is -greater than or equal to the second.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public static let uge = unsignedGreaterThanOrEqual
      - -
      -
      -
      -
      -
    • -
    • -
      - - - - ult - -
      -
      -
      -
      -
      -
      -

      Interprets the operands as unsigned values and yields true if the first is -less than the second.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public static let ult = unsignedLessThan
      - -
      -
      -
      -
      -
    • -
    • -
      - - - - ule - -
      -
      -
      -
      -
      -
      -

      Interprets the operands as unsigned values and yields true if the first is -less than or equal to the second.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public static let ule = unsignedLessThanOrEqual
      - -
      -
      -
      -
      -
    • -
    • -
      - - - - sgt - -
      -
      -
      -
      -
      -
      -

      Interprets the operands as signed values and yields true if the first is -greater than the second.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public static let sgt = signedGreaterThan
      - -
      -
      -
      -
      -
    • -
    • -
      - - - - sge - -
      -
      -
      -
      -
      -
      -

      Interprets the operands as signed values and yields true if the first is -greater than or equal to the second.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public static let sge = signedGreaterThanOrEqual
      - -
      -
      -
      -
      -
    • -
    • -
      - - - - slt - -
      -
      -
      -
      -
      -
      -

      Interprets the operands as signed values and yields true if the first is -less than the second.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public static let slt = signedLessThan
      - -
      -
      -
      -
      -
    • -
    • -
      @@ -969,7 +860,7 @@

      Declaration

      Declaration

      Swift

      -
      public static let sle = signedLessThanOrEqual
      +
      case signedLessThanOrEqual
      @@ -981,8 +872,8 @@

      Declaration

    diff --git a/docs/Enums/JITError.html b/docs/Enums/JITError.html index 69ae710e..247face6 100644 --- a/docs/Enums/JITError.html +++ b/docs/Enums/JITError.html @@ -1,27 +1,35 @@ - JITError Enum Reference + JITError Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    -
    -
      -
    • -
      - - - - couldNotRemoveModule - -
      -
      -
      -
      -
      -
      -

      The JIT was unable to remove the provided module. A message is provided -explaining the failure

      +

      In general, it is not safe to catch and continue after this exception has +been thrown.

      Declaration

      Swift

      -
      case couldNotRemoveModule(Module, String)
      +
      case generic(String)
    • -
    -
    -
    -
    - - -
    -
    - - -
    -
    • - + - asLLVM() + asLLVM()
      @@ -449,7 +683,7 @@

      Declaration

      Declaration

      Swift

      -
      public func asLLVM() -> LLVMValueRef
      +
      public func asLLVM() -> LLVMValueRef
      @@ -461,8 +695,8 @@

      Declaration

    diff --git a/docs/Enums/Linkage.html b/docs/Enums/Linkage.html index 9243bcd6..dd4ae311 100644 --- a/docs/Enums/Linkage.html +++ b/docs/Enums/Linkage.html @@ -1,27 +1,35 @@ - Linkage Enum Reference + Linkage Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • @@ -396,7 +634,7 @@

      Declaration

      Available for inspection, not emission.

      -

      Globals with available_externally linkage are never emitted into the +

      Globals with “available_externally” linkage are never emitted into the object file corresponding to the LLVM module. From the linker’s perspective, an available_externally global is equivalent to an external declaration. They exist to allow inlining and other optimizations to take @@ -411,23 +649,19 @@

      Declaration

      Declaration

      Swift

      -
      case availableExternally
      +
      case availableExternally
    • -
    -
    -
    -
    • @@ -437,7 +671,7 @@

      Declaration

      Keep one copy of function when linking.

      -

      Globals with linkonce linkage are merged with other globals of the same +

      Globals with “linkonce” linkage are merged with other globals of the same name when linkage occurs. This can be used to implement some forms of inline functions, templates, or other code which must be generated in each translation unit that uses it, but where the body may be overridden with a @@ -453,23 +687,19 @@

      Declaration

      Declaration

      Swift

      -
      case linkOnceAny
      +
      case linkOnceAny
    • -
    -
    -
    -
    • @@ -482,7 +712,7 @@

      Declaration

      Some languages allow differing globals to be merged, such as two functions with different semantics. Other languages, such as C++, ensure that only -equivalent globals are ever merged (the one definition ruleODR). +equivalent globals are ever merged (the “one definition rule” — “ODR”). Such languages can use the linkonce_odr and weak_odr linkage types to indicate that the global will only be merged with equivalent globals. These linkage types are otherwise the same as their non-odr versions.

      @@ -492,23 +722,19 @@

      Declaration

      Declaration

      Swift

      -
      case linkOnceODR
      +
      case linkOnceODR
    - - -
    -
    • - + - weakAny + weakAny
      @@ -518,32 +744,28 @@

      Declaration

      Keep one copy of function when linking (weak).

      -

      weak linkage has the same merging semantics as linkonce linkage, except +

      “weak” linkage has the same merging semantics as linkonce linkage, except that unreferenced globals with weak linkage may not be discarded. This is -used for globals that are declared weak in C source code.

      +used for globals that are declared “weak” in C source code.

      Declaration

      Swift

      -
      case weakAny
      +
      case weakAny
    • -
    -
    -
    -
    • - + - weakODR + weakODR
      @@ -551,12 +773,12 @@

      Declaration

      -

      Keep one copy of function when linking but apply One Definition Rule +

      Keep one copy of function when linking but apply “One Definition Rule” semantics.

      Some languages allow differing globals to be merged, such as two functions with different semantics. Other languages, such as C++, ensure that only -equivalent globals are ever merged (the one definition ruleODR). +equivalent globals are ever merged (the “one definition rule” — “ODR”). Such languages can use the linkonce_odr and weak_odr linkage types to indicate that the global will only be merged with equivalent globals. These linkage types are otherwise the same as their non-odr versions.

      @@ -566,23 +788,19 @@

      Declaration

      Declaration

      Swift

      -
      case weakODR
      +
      case weakODR
    • -
    -
    -
    -
    • @@ -592,11 +810,11 @@

      Declaration

      Special purpose, only applies to global arrays.

      -

      appending linkage may only be applied to global variables of pointer to +

      “appending” linkage may only be applied to global variables of pointer to array type. When two global variables with appending linkage are linked together, the two global arrays are appended together. This is the LLVM, typesafe, equivalent of having the system linker append together -sections with identical names when .o files are linked.

      +“sections” with identical names when .o files are linked.

      Unfortunately this doesn’t correspond to any feature in .o files, so it can only be used for variables like llvm.global_ctors which llvm @@ -607,23 +825,19 @@

      Declaration

      Declaration

      Swift

      -
      case appending
      +
      case appending
    • -
    -
    -
    -
    • - + - internal + internal
      @@ -642,23 +856,19 @@

      Declaration

      Declaration

      Swift

      -
      case `internal`
      +
      case `internal`
    - - -
    -
    • - + - private + private
      @@ -666,9 +876,9 @@

      Declaration

      -

      Like .internal, but omit from symbol table.

      +

      Like .internal, but omit from symbol table.

      -

      Global values with private linkage are only directly accessible by +

      Global values with “private” linkage are only directly accessible by objects in the current module. In particular, linking code into a module with an private global value may cause the private to be renamed as necessary to avoid collisions. Because the symbol is private to the @@ -680,23 +890,19 @@

      Declaration

      Declaration

      Swift

      -
      case `private`
      +
      case `private`
    • -
    -
    -
    -
    • @@ -715,23 +921,19 @@

      Declaration

      Declaration

      Swift

      -
      case externalWeak
      +
      case externalWeak
    - - -
    -
    • - + - common + common
      @@ -741,9 +943,9 @@

      Declaration

      Tentative definitions.

      -

      common linkage is most similar to weak linkage, but they are used for -tentative definitions in C, such as int X; at global scope. Symbols with -common linkage are merged in the same way as weak symbols, and they may +

      “common” linkage is most similar to “weak” linkage, but they are used for +tentative definitions in C, such as “int X;” at global scope. Symbols with +“common” linkage are merged in the same way as weak symbols, and they may not be deleted if unreferenced. common symbols may not have an explicit section, must have a zero initializer, and may not be marked ‘constant‘. Functions and aliases may not have common linkage.

      @@ -753,23 +955,19 @@

      Declaration

      Declaration

      Swift

      -
      case common
      +
      case common
    • -
    -
    -
    -
    • - + - llvm + llvm
      @@ -784,7 +982,7 @@

      Declaration

      Declaration

      Swift

      -
      public var llvm: LLVMLinkage
      +
      public var llvm: LLVMLinkage { get }
      @@ -796,8 +994,8 @@

      Declaration

    diff --git a/docs/Enums/MemoryBufferError.html b/docs/Enums/MemoryBufferError.html index 0cfd0cf4..e4ae94f1 100644 --- a/docs/Enums/MemoryBufferError.html +++ b/docs/Enums/MemoryBufferError.html @@ -1,27 +1,35 @@ - MemoryBufferError Enum Reference + MemoryBufferError Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    diff --git a/docs/Enums/ModuleError.html b/docs/Enums/ModuleError.html index e614d1d0..8382c99c 100644 --- a/docs/Enums/ModuleError.html +++ b/docs/Enums/ModuleError.html @@ -1,27 +1,35 @@ - ModuleError Enum Reference + ModuleError Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • @@ -399,23 +637,19 @@

      Declaration

      Declaration

      Swift

      -
      case couldNotPrint(path: String, error: String)
      +
      case couldNotPrint(path: String, error: String)
    - - -
    -
    - - -
    -
    • @@ -461,7 +691,7 @@

      Declaration

      Declaration

      Swift

      -
      public var description: String
      +
      public var description: String { get }
      @@ -473,8 +703,8 @@

      Declaration

    diff --git a/docs/Enums/OpCode.html b/docs/Enums/OpCode.html index fdc47465..0fd989a9 100644 --- a/docs/Enums/OpCode.html +++ b/docs/Enums/OpCode.html @@ -1,27 +1,35 @@ - OpCode Enum Reference + OpCode Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • - + - br + br
      @@ -396,23 +643,19 @@

      Declaration

      Declaration

      Swift

      -
      case br
      +
      case br
    - - -
    -
    • - + - switch + switch
      @@ -427,23 +670,19 @@

      Declaration

      Declaration

      Swift

      -
      case `switch`
      +
      case `switch`
    - - -
    -
    • @@ -458,23 +697,19 @@

      Declaration

      Declaration

      Swift

      -
      case indirectBr
      +
      case indirectBr
    - - -
    -
    • - + - invoke + invoke
      @@ -489,23 +724,19 @@

      Declaration

      Declaration

      Swift

      -
      case invoke
      +
      case invoke
    - - -
    -
    • @@ -520,7 +751,7 @@

      Declaration

      Declaration

      Swift

      -
      case unreachable
      +
      case unreachable
      @@ -530,13 +761,22 @@

      Declaration

    +
    + + +
    + +

    Standard Binary Operators

    +

    +
    +
    • - + - add + add
      @@ -551,23 +791,19 @@

      Declaration

      Declaration

      Swift

      -
      case add
      +
      case add
    - - -
    -
    • - + - fadd + fadd
      @@ -582,23 +818,19 @@

      Declaration

      Declaration

      Swift

      -
      case fadd
      +
      case fadd
    - - -
    -
    • - + - sub + sub
      @@ -613,23 +845,19 @@

      Declaration

      Declaration

      Swift

      -
      case sub
      +
      case sub
    - - -
    -
    • - + - fsub + fsub
      @@ -644,23 +872,19 @@

      Declaration

      Declaration

      Swift

      -
      case fsub
      +
      case fsub
    - - -
    -
    • - + - mul + mul
      @@ -675,23 +899,19 @@

      Declaration

      Declaration

      Swift

      -
      case mul
      +
      case mul
    - - -
    -
    • - + - fmul + fmul
      @@ -706,23 +926,19 @@

      Declaration

      Declaration

      Swift

      -
      case fmul
      +
      case fmul
    - - -
    -
    • - + - udiv + udiv
      @@ -737,23 +953,19 @@

      Declaration

      Declaration

      Swift

      -
      case udiv
      +
      case udiv
    - - -
    -
    • - + - sdiv + sdiv
      @@ -768,23 +980,19 @@

      Declaration

      Declaration

      Swift

      -
      case sdiv
      +
      case sdiv
    - - -
    -
    • - + - fdiv + fdiv
      @@ -799,23 +1007,19 @@

      Declaration

      Declaration

      Swift

      -
      case fdiv
      +
      case fdiv
    - - -
    -
    • - + - urem + urem
      @@ -830,23 +1034,19 @@

      Declaration

      Declaration

      Swift

      -
      case urem
      +
      case urem
    - - -
    -
    • - + - srem + srem
      @@ -861,23 +1061,19 @@

      Declaration

      Declaration

      Swift

      -
      case srem
      +
      case srem
    - - -
    -
    • - + - frem + frem
      @@ -892,7 +1088,7 @@

      Declaration

      Declaration

      Swift

      -
      case frem
      +
      case frem
      @@ -902,13 +1098,22 @@

      Declaration

    +
    + + +
    + +

    Logical Operators

    +

    +
    +
    • - + - shl + shl
      @@ -923,23 +1128,19 @@

      Declaration

      Declaration

      Swift

      -
      case shl
      +
      case shl
    - - -
    -
    • - + - lshr + lshr
      @@ -954,23 +1155,19 @@

      Declaration

      Declaration

      Swift

      -
      case lshr
      +
      case lshr
    - - -
    -
    • - + - ashr + ashr
      @@ -985,23 +1182,19 @@

      Declaration

      Declaration

      Swift

      -
      case ashr
      +
      case ashr
    - - -
    -
    • - + - and + and
      @@ -1016,23 +1209,19 @@

      Declaration

      Declaration

      Swift

      -
      case and
      +
      case and
    - - -
    -
    • - + - or + or
      @@ -1047,23 +1236,19 @@

      Declaration

      Declaration

      Swift

      -
      case or
      +
      case or
    - - -
    -
    • - + - xor + xor
      @@ -1078,7 +1263,7 @@

      Declaration

      Declaration

      Swift

      -
      case xor
      +
      case xor
      @@ -1088,13 +1273,22 @@

      Declaration

    +
    + + +
    + +

    Memory Operators

    +

    +
    +
    • - + - alloca + alloca
      @@ -1109,23 +1303,19 @@

      Declaration

      Declaration

      Swift

      -
      case alloca
      +
      case alloca
    - - -
    -
    • - + - load + load
      @@ -1140,23 +1330,19 @@

      Declaration

      Declaration

      Swift

      -
      case load
      +
      case load
    - - -
    -
    • - + - store + store
      @@ -1171,23 +1357,19 @@

      Declaration

      Declaration

      Swift

      -
      case store
      +
      case store
    - - -
    -
    • @@ -1202,7 +1384,7 @@

      Declaration

      Declaration

      Swift

      -
      case getElementPtr
      +
      case getElementPtr
      @@ -1212,13 +1394,22 @@

      Declaration

    +
    + + +
    + +

    Cast Operators

    +

    +
    +
    • - + - trunc + trunc
      @@ -1233,23 +1424,19 @@

      Declaration

      Declaration

      Swift

      -
      case trunc
      +
      case trunc
    - - -
    -
    • - + - zext + zext
      @@ -1264,23 +1451,19 @@

      Declaration

      Declaration

      Swift

      -
      case zext
      +
      case zext
    - - -
    -
    • - + - sext + sext
      @@ -1295,23 +1478,19 @@

      Declaration

      Declaration

      Swift

      -
      case sext
      +
      case sext
    - - -
    -
    • - + - fpToUI + fpToUI
      @@ -1326,23 +1505,19 @@

      Declaration

      Declaration

      Swift

      -
      case fpToUI
      +
      case fpToUI
    - - -
    -
    • - + - fpToSI + fpToSI
      @@ -1357,23 +1532,19 @@

      Declaration

      Declaration

      Swift

      -
      case fpToSI
      +
      case fpToSI
    - - -
    -
    • - + - uiToFP + uiToFP
      @@ -1388,23 +1559,19 @@

      Declaration

      Declaration

      Swift

      -
      case uiToFP
      +
      case uiToFP
    - - -
    -
    • - + - siToFP + siToFP
      @@ -1419,23 +1586,19 @@

      Declaration

      Declaration

      Swift

      -
      case siToFP
      +
      case siToFP
    - - -
    -
    • - + - fpTrunc + fpTrunc
      @@ -1450,23 +1613,19 @@

      Declaration

      Declaration

      Swift

      -
      case fpTrunc
      +
      case fpTrunc
    - - -
    -
    • - + - fpExt + fpExt
      @@ -1481,23 +1640,19 @@

      Declaration

      Declaration

      Swift

      -
      case fpExt
      +
      case fpExt
    - - -
    -
    • - + - ptrToInt + ptrToInt
      @@ -1512,23 +1667,19 @@

      Declaration

      Declaration

      Swift

      -
      case ptrToInt
      +
      case ptrToInt
    - - -
    -
    • - + - intToPtr + intToPtr
      @@ -1543,23 +1694,19 @@

      Declaration

      Declaration

      Swift

      -
      case intToPtr
      +
      case intToPtr
    - - -
    -
    • - + - bitCast + bitCast
      @@ -1574,23 +1721,19 @@

      Declaration

      Declaration

      Swift

      -
      case bitCast
      +
      case bitCast
    - - -
    -
    • @@ -1605,7 +1748,7 @@

      Declaration

      Declaration

      Swift

      -
      case addrSpaceCast
      +
      case addrSpaceCast
      @@ -1615,13 +1758,22 @@

      Declaration

    +
    + + +
    + +

    Other Operators

    +

    +
    +
    • - + - icmp + icmp
      @@ -1636,23 +1788,19 @@

      Declaration

      Declaration

      Swift

      -
      case icmp
      +
      case icmp
    - - -
    -
    • - + - fcmp + fcmp
      @@ -1667,23 +1815,19 @@

      Declaration

      Declaration

      Swift

      -
      case fcmp
      +
      case fcmp
    - - -
    -
    • - + - phi + phi
      @@ -1698,23 +1842,19 @@

      Declaration

      Declaration

      Swift

      -
      case phi
      +
      case phi
    - - -
    -
    • - + - call + call
      @@ -1729,23 +1869,19 @@

      Declaration

      Declaration

      Swift

      -
      case call
      +
      case call
    - - -
    -
    • - + - select + select
      @@ -1760,23 +1896,19 @@

      Declaration

      Declaration

      Swift

      -
      case select
      +
      case select
    - - -
    -
    • - + - userOp1 + userOp1
      @@ -1791,23 +1923,19 @@

      Declaration

      Declaration

      Swift

      -
      case userOp1
      +
      case userOp1
    - - -
    -
    • - + - userOp2 + userOp2
      @@ -1822,23 +1950,19 @@

      Declaration

      Declaration

      Swift

      -
      case userOp2
      +
      case userOp2
    - - -
    -
    • - + - vaArg + vaArg
      @@ -1853,23 +1977,19 @@

      Declaration

      Declaration

      Swift

      -
      case vaArg
      +
      case vaArg
    - - -
    -
    - - -
    -
    • @@ -1915,23 +2031,19 @@

      Declaration

      Declaration

      Swift

      -
      case insertElement
      +
      case insertElement
    - - -
    -
    • @@ -1946,23 +2058,19 @@

      Declaration

      Declaration

      Swift

      -
      case shuffleVector
      +
      case shuffleVector
    - - -
    -
    • @@ -1977,23 +2085,19 @@

      Declaration

      Declaration

      Swift

      -
      case extractValue
      +
      case extractValue
    - - -
    -
    • @@ -2008,7 +2112,7 @@

      Declaration

      Declaration

      Swift

      -
      case insertValue
      +
      case insertValue
      @@ -2018,13 +2122,22 @@

      Declaration

    +
    + + +
    + +

    Atomic operators

    +

    +
    +
    • - + - fence + fence
      @@ -2039,23 +2152,19 @@

      Declaration

      Declaration

      Swift

      -
      case fence
      +
      case fence
    - - -
    -
    • @@ -2070,23 +2179,19 @@

      Declaration

      Declaration

      Swift

      -
      case atomicCmpXchg
      +
      case atomicCmpXchg
    - - -
    -
    • @@ -2101,7 +2206,7 @@

      Declaration

      Declaration

      Swift

      -
      case atomicRMW
      +
      case atomicRMW
      @@ -2111,13 +2216,22 @@

      Declaration

    +
    + + +
    + +

    Exception Handling Operators

    +

    +
    +
    • - + - resume + resume
      @@ -2132,23 +2246,19 @@

      Declaration

      Declaration

      Swift

      -
      case resume
      +
      case resume
    - - -
    -
    • @@ -2163,23 +2273,19 @@

      Declaration

      Declaration

      Swift

      -
      case landingPad
      +
      case landingPad
    - - -
    -
    • @@ -2194,23 +2300,19 @@

      Declaration

      Declaration

      Swift

      -
      case cleanupRet
      +
      case cleanupRet
    - - -
    -
    • - + - catchRet + catchRet
      @@ -2225,23 +2327,19 @@

      Declaration

      Declaration

      Swift

      -
      case catchRet
      +
      case catchRet
    - - -
    -
    • - + - catchPad + catchPad
      @@ -2256,23 +2354,19 @@

      Declaration

      Declaration

      Swift

      -
      case catchPad
      +
      case catchPad
    - - -
    -
    • @@ -2287,23 +2381,19 @@

      Declaration

      Declaration

      Swift

      -
      case cleanupPad
      +
      case cleanupPad
    - - -
    -
    • @@ -2318,23 +2408,19 @@

      Declaration

      Declaration

      Swift

      -
      case catchSwitch
      +
      case catchSwitch
    - - -
    -
    • - + - Binary + Binary
      @@ -2350,7 +2436,7 @@

      Declaration

      Declaration

      Swift

      -
      public enum Binary
      +
      public enum Binary : CaseIterable
      @@ -2360,9 +2446,9 @@

      Declaration

    • - + - Cast + Cast
      @@ -2378,7 +2464,7 @@

      Declaration

      Declaration

      Swift

      -
      public enum Cast
      +
      public enum Cast : CaseIterable
      @@ -2390,8 +2476,8 @@

      Declaration

    diff --git a/docs/Enums/OpCode/Binary.html b/docs/Enums/OpCode/Binary.html index bedec180..5091dab4 100644 --- a/docs/Enums/OpCode/Binary.html +++ b/docs/Enums/OpCode/Binary.html @@ -1,27 +1,35 @@ - Binary Enum Reference + Binary Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • - + - fadd + fadd
      @@ -396,23 +634,19 @@

      Declaration

      Declaration

      Swift

      -
      case fadd
      +
      case fadd
    - - -
    -
    • - + - sub + sub
      @@ -427,23 +661,19 @@

      Declaration

      Declaration

      Swift

      -
      case sub
      +
      case sub
    - - -
    -
    • - + - fsub + fsub
      @@ -458,23 +688,19 @@

      Declaration

      Declaration

      Swift

      -
      case fsub
      +
      case fsub
    - - -
    -
    • - + - mul + mul
      @@ -489,23 +715,19 @@

      Declaration

      Declaration

      Swift

      -
      case mul
      +
      case mul
    - - -
    -
    • - + - fmul + fmul
      @@ -520,23 +742,19 @@

      Declaration

      Declaration

      Swift

      -
      case fmul
      +
      case fmul
    - - -
    -
    • - + - udiv + udiv
      @@ -551,23 +769,19 @@

      Declaration

      Declaration

      Swift

      -
      case udiv
      +
      case udiv
    - - -
    -
    • - + - sdiv + sdiv
      @@ -582,23 +796,19 @@

      Declaration

      Declaration

      Swift

      -
      case sdiv
      +
      case sdiv
    - - -
    -
    • - + - fdiv + fdiv
      @@ -613,23 +823,19 @@

      Declaration

      Declaration

      Swift

      -
      case fdiv
      +
      case fdiv
    - - -
    -
    • - + - urem + urem
      @@ -644,23 +850,19 @@

      Declaration

      Declaration

      Swift

      -
      case urem
      +
      case urem
    - - -
    -
    • - + - srem + srem
      @@ -675,23 +877,19 @@

      Declaration

      Declaration

      Swift

      -
      case srem
      +
      case srem
    - - -
    -
    • - + - frem + frem
      @@ -706,23 +904,19 @@

      Declaration

      Declaration

      Swift

      -
      case frem
      +
      case frem
    - - -
    -
    • - + - shl + shl
      @@ -737,23 +931,19 @@

      Declaration

      Declaration

      Swift

      -
      case shl
      +
      case shl
    - - -
    -
    • - + - lshr + lshr
      @@ -768,23 +958,19 @@

      Declaration

      Declaration

      Swift

      -
      case lshr
      +
      case lshr
    - - -
    -
    • - + - ashr + ashr
      @@ -799,23 +985,19 @@

      Declaration

      Declaration

      Swift

      -
      case ashr
      +
      case ashr
    - - -
    -
    • - + - and + and
      @@ -830,23 +1012,19 @@

      Declaration

      Declaration

      Swift

      -
      case and
      +
      case and
    - - -
    -
    • - + - or + or
      @@ -861,23 +1039,19 @@

      Declaration

      Declaration

      Swift

      -
      case or
      +
      case or
    - - -
    -
    • - + - xor + xor
      @@ -892,23 +1066,19 @@

      Declaration

      Declaration

      Swift

      -
      case xor
      +
      case xor
    - - -
    -
    • - + - llvm + llvm
      @@ -923,7 +1093,34 @@

      Declaration

      Declaration

      Swift

      -
      public var llvm: LLVMOpcode
      +
      public var llvm: LLVMOpcode { get }
      + +
      +
      + +
    + +
  • +
    + + + + opCode + +
    +
    +
    +
    +
    +
    +

    Retrieves the corresponding opcode for this binary operation.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var opCode: OpCode { get }
    @@ -935,8 +1132,8 @@

    Declaration

    diff --git a/docs/Enums/OpCode/Cast.html b/docs/Enums/OpCode/Cast.html index fffbee0e..571b1079 100644 --- a/docs/Enums/OpCode/Cast.html +++ b/docs/Enums/OpCode/Cast.html @@ -1,27 +1,35 @@ - Cast Enum Reference + Cast Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
  • - - -
    -
    • - + - sext + sext
      @@ -427,23 +661,19 @@

      Declaration

      Declaration

      Swift

      -
      case sext
      +
      case sext
    - - -
    -
    • - + - fpToUI + fpToUI
      @@ -458,23 +688,19 @@

      Declaration

      Declaration

      Swift

      -
      case fpToUI
      +
      case fpToUI
    - - -
    -
    • - + - fpToSI + fpToSI
      @@ -489,23 +715,19 @@

      Declaration

      Declaration

      Swift

      -
      case fpToSI
      +
      case fpToSI
    - - -
    -
    • - + - uiToFP + uiToFP
      @@ -520,23 +742,19 @@

      Declaration

      Declaration

      Swift

      -
      case uiToFP
      +
      case uiToFP
    - - -
    -
    • - + - siToFP + siToFP
      @@ -551,23 +769,19 @@

      Declaration

      Declaration

      Swift

      -
      case siToFP
      +
      case siToFP
    - - -
    -
    • - + - fpTrunc + fpTrunc
      @@ -582,23 +796,19 @@

      Declaration

      Declaration

      Swift

      -
      case fpTrunc
      +
      case fpTrunc
    - - -
    -
    • - + - fpext + fpext
      @@ -613,23 +823,19 @@

      Declaration

      Declaration

      Swift

      -
      case fpext
      +
      case fpext
    - - -
    -
    • - + - ptrToInt + ptrToInt
      @@ -644,23 +850,19 @@

      Declaration

      Declaration

      Swift

      -
      case ptrToInt
      +
      case ptrToInt
    - - -
    -
    • - + - intToPtr + intToPtr
      @@ -675,23 +877,19 @@

      Declaration

      Declaration

      Swift

      -
      case intToPtr
      +
      case intToPtr
    - - -
    -
    • - + - bitCast + bitCast
      @@ -706,23 +904,19 @@

      Declaration

      Declaration

      Swift

      -
      case bitCast
      +
      case bitCast
    - - -
    -
    • @@ -737,23 +931,19 @@

      Declaration

      Declaration

      Swift

      -
      case addrSpaceCast
      +
      case addrSpaceCast
    - - -
    -
    • - + - llvm + llvm
      @@ -768,7 +958,34 @@

      Declaration

      Declaration

      Swift

      -
      public var llvm: LLVMOpcode
      +
      public var llvm: LLVMOpcode { get }
      + +
      +
      + +
    + +
  • +
    + + + + opCode + +
    +
    +
    +
    +
    +
    +

    Retrieves the corresponding opcode for this cast operation.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var opCode: OpCode { get }
    @@ -780,8 +997,8 @@

    Declaration

    diff --git a/docs/Enums/OverflowBehavior.html b/docs/Enums/OverflowBehavior.html index a55530a7..077b1aa7 100644 --- a/docs/Enums/OverflowBehavior.html +++ b/docs/Enums/OverflowBehavior.html @@ -1,27 +1,35 @@ - OverflowBehavior Enum Reference + OverflowBehavior Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
  • - - -
    -
    • @@ -431,7 +665,7 @@

      Declaration

      Declaration

      Swift

      -
      case noUnsignedWrap
      +
      case noUnsignedWrap
      @@ -443,8 +677,8 @@

      Declaration

    diff --git a/docs/Enums/Pass.html b/docs/Enums/Pass.html new file mode 100644 index 00000000..2d44cd76 --- /dev/null +++ b/docs/Enums/Pass.html @@ -0,0 +1,2270 @@ + + + + Pass Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    Pass

    +
    +
    + +
    public enum Pass
    + +
    +
    +

    A subset of supported LLVM IR optimizer passes.

    + +
    +
    +
    +
      +
    • +
      + + + + aggressiveDCE + +
      +
      +
      +
      +
      +
      +

      This pass uses the SSA based Aggressive DCE algorithm. This algorithm +assumes instructions are dead until proven otherwise, which makes +it more successful are removing non-obviously dead instructions.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case aggressiveDCE
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + bitTrackingDCE + +
      +
      +
      +
      +
      +
      +

      This pass uses a bit-tracking DCE algorithm in order to remove +computations of dead bits.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case bitTrackingDCE
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Use assume intrinsics to set load/store alignments.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case alignmentFromAssumptions
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + cfgSimplification + +
      +
      +
      +
      +
      +
      +

      Merge basic blocks, eliminate unreachable blocks, simplify terminator +instructions, etc.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case cfgSimplification
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + deadStoreElimination + +
      +
      +
      +
      +
      +
      +

      This pass deletes stores that are post-dominated by must-aliased stores +and are not loaded used between the stores.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case deadStoreElimination
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + scalarizer + +
      +
      +
      +
      +
      +
      +

      Converts vector operations into scalar operations.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case scalarizer
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + mergedLoadStoreMotion + +
      +
      +
      +
      +
      +
      +

      This pass merges loads and stores in diamonds. Loads are hoisted into the +header, while stores sink into the footer.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case mergedLoadStoreMotion
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + gvn + +
      +
      +
      +
      +
      +
      +

      This pass performs global value numbering and redundant load elimination +cotemporaneously.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case gvn
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + indVarSimplify + +
      +
      +
      +
      +
      +
      +

      Transform induction variables in a program to all use a single canonical +induction variable per loop.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case indVarSimplify
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + instructionCombining + +
      +
      +
      +
      +
      +
      +

      Combine instructions to form fewer, simple instructions. This pass does +not modify the CFG, and has a tendency to make instructions dead, so a +subsequent DCE pass is useful.

      + +

      This pass combines things like:

      +
      %Y = add int 1, %X
      +%Z = add int 1, %Y
      +
      + +

      into:

      +
      %Z = add int 2, %X
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case instructionCombining
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Working in conjunction with the linker, iterate through all functions and +global values in the module and attempt to change their linkage from +external to internal.

      + +

      To preserve the linkage of a global value, return true from the given +callback.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case internalize(mustPreserve: (IRGlobal) -> Bool)
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Working in conjunction with the linker, iterate through all functions and +global values in the module and attempt to change their linkage from +external to internal.

      + +

      When a function with the name “main” is encountered, if the value of +preserveMain is true, “main” will not be internalized.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case internalizeAll(preserveMain: Bool)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + jumpThreading + +
      +
      +
      +
      +
      +
      +

      Thread control through mult-pred/multi-succ blocks where some preds +always go to some succ. Thresholds other than minus one override the +internal BB duplication default threshold.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case jumpThreading
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + licm + +
      +
      +
      +
      +
      +
      +

      This pass is a loop invariant code motion and memory promotion pass.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case licm
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + loopDeletion + +
      +
      +
      +
      +
      +
      +

      This pass performs DCE of non-infinite loops that it can prove are dead.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case loopDeletion
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + loopIdiom + +
      +
      +
      +
      +
      +
      +

      This pass recognizes and replaces idioms in loops.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case loopIdiom
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + loopRotate + +
      +
      +
      +
      +
      +
      +

      This pass is a simple loop rotating pass.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case loopRotate
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + loopReroll + +
      +
      +
      +
      +
      +
      +

      This pass is a simple loop rerolling pass.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case loopReroll
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + loopUnroll + +
      +
      +
      +
      +
      +
      +

      This pass is a simple loop unrolling pass.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case loopUnroll
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + loopUnrollAndJam + +
      +
      +
      +
      +
      +
      +

      This pass is a simple loop unroll-and-jam pass.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case loopUnrollAndJam
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + loopUnswitch + +
      +
      +
      +
      +
      +
      +

      This pass is a simple loop unswitching pass.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case loopUnswitch
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + lowerAtomic + +
      +
      +
      +
      +
      +
      +

      This pass lowers atomic intrinsics to non-atomic form for use in a known +non-preemptible environment.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case lowerAtomic
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + memCpyOpt + +
      +
      +
      +
      +
      +
      +

      This pass performs optimizations related to eliminating memcpy calls +and/or combining multiple stores into memset’s.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case memCpyOpt
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Tries to inline the fast path of library calls such as sqrt.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case partiallyInlineLibCalls
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + lowerSwitch + +
      +
      +
      +
      +
      +
      +

      This pass converts SwitchInst instructions into a sequence of chained +binary branch instructions.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case lowerSwitch
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      This pass is used to promote memory references to +be register references. A simple example of the transformation performed +by this pass is going from code like this:

      +
      %X = alloca i32, i32 1
      +store i32 42, i32 *%X
      +%Y = load i32* %X
      +ret i32 %Y
      +
      + +

      To code like this:

      +
      ret i32 42
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case promoteMemoryToRegister
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + addDiscriminators + +
      +
      +
      +
      +
      +
      +

      Adds DWARF discriminators to the IR. Discriminators are +used to decide what CFG path was taken inside sub-graphs whose instructions +share the same line and column number information.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case addDiscriminators
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + reassociate + +
      +
      +
      +
      +
      +
      +

      This pass reassociates commutative expressions in an order that +is designed to promote better constant propagation, GCSE, LICM, PRE, etc.

      + +

      For example:

      +
      4 + (x + 5)  ->  x + (4 + 5)
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case reassociate
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + sccp + +
      +
      +
      +
      +
      +
      +

      Sparse conditional constant propagation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case sccp
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + tailCallElimination + +
      +
      +
      +
      +
      +
      +

      This pass eliminates call instructions to the current function which occur +immediately before return instructions.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case tailCallElimination
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + constantPropagation + +
      +
      +
      +
      +
      +
      +

      A worklist driven constant propagation pass.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case constantPropagation
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      This pass is used to demote registers to memory references. It basically +undoes the .promoteMemoryToRegister pass to make CFG hacking easier.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case demoteMemoryToRegister
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Propagate CFG-derived value information

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case correlatedValuePropagation
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + earlyCSE + +
      +
      +
      +
      +
      +
      +

      This pass performs a simple and fast CSE pass over the dominator tree.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case earlyCSE
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + lowerExpectIntrinsic + +
      +
      +
      +
      +
      +
      +

      Removes llvm.expect intrinsics and creates “block_weights” metadata.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case lowerExpectIntrinsic
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Adds metadata to LLVM IR types and performs metadata-based +Type-Based Alias Analysis (TBAA).

      + +

      TBAA requires that two pointers to objects of different types must never +alias. Because memory in LLVM is typeless, TBAA is performed using +special metadata nodes describing aliasing relationships between types +in the source language(s).

      + +

      To construct this metadata, see MDBuilder.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case typeBasedAliasAnalysis
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + scopedNoAliasAA + +
      +
      +
      +
      +
      +
      +

      Adds metadata to LLVM IR types and performs metadata-based scoped no-alias +analysis.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case scopedNoAliasAA
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + basicAliasAnalysis + +
      +
      +
      +
      +
      +
      +

      LLVM’s primary stateless and local alias analysis.

      + +

      Given a pointer value, walk the use-def chain to find out how that +pointer is used. The traversal terminates at global variables and +aliases, stack allocations, and values of non-pointer types - referred +to as “underlying objects”. Analysis may reach multiple underlying object +values because of branching control flow. If the set of underlying +objects for one pointer has a non-empty intersection with another, those +two pointers are deemed mayalias. Else, an empty intersection deems +those pointers noalias.

      + +

      Basic Alias Analysis should generally be scheduled ahead of other +AA passes. This is because it is more conservative than other passes +about declaring two pointers mustalias, and does so fairly efficiently. +For example, loads through two members of a union with distinct types are +declared by TBAA to be noalias, where BasicAA considers them +mustalias.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case basicAliasAnalysis
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + globalsAliasAnalysis + +
      +
      +
      +
      +
      +
      +

      Performs alias and mod/ref analysis for internal global values that +do not have their address taken.

      + +

      Internal global variables that are only loaded from may be marked as +constants.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case globalsAliasAnalysis
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      This pass is used to ensure that functions have at most one return +instruction in them. Additionally, it keeps track of which node is +the new exit node of the CFG.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case unifyFunctionExitNodes
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + verifier + +
      +
      +
      +
      +
      +
      +

      Runs the LLVM IR Verifier to sanity check the results of passes.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case verifier
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + alwaysInliner + +
      +
      +
      +
      +
      +
      +

      A pass to inline and remove functions marked as “always_inline”.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case alwaysInliner
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + argumentPromotion + +
      +
      +
      +
      +
      +
      +

      This pass promotes “by reference” arguments to be passed by value if the +number of elements passed is less than or equal to 3.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case argumentPromotion
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + constantMerge + +
      +
      +
      +
      +
      +
      +

      This function returns a new pass that merges duplicate global constants +together into a single constant that is shared. This is useful because +some passes (ie TraceValues) insert a lot of string constants into the +program, regardless of whether or not they duplicate an existing string.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case constantMerge
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + deadArgElimination + +
      +
      +
      +
      +
      +
      +

      This pass removes arguments from functions which are not used by the body +of the function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case deadArgElimination
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + functionAttrs + +
      +
      +
      +
      +
      +
      +

      This pass walks SCCs of the call graph in RPO to deduce and propagate +function attributes. Currently it only handles synthesizing norecurse +attributes.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case functionAttrs
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + functionInlining + +
      +
      +
      +
      +
      +
      +

      Uses a heuristic to inline direct function calls to small functions.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case functionInlining
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + globalDCE + +
      +
      +
      +
      +
      +
      +

      This transform is designed to eliminate unreachable internal globals +(functions or global variables)

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case globalDCE
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + globalOptimizer + +
      +
      +
      +
      +
      +
      +

      This function returns a new pass that optimizes non-address taken internal +globals.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case globalOptimizer
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ipConstantPropagation + +
      +
      +
      +
      +
      +
      +

      This pass propagates constants from call sites into the bodies of +functions.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case ipConstantPropagation
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ipscc + +
      +
      +
      +
      +
      +
      +

      This pass propagates constants from call sites into the bodies of +functions, and keeps track of whether basic blocks are executable in the +process.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case ipscc
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + pruneEH + +
      +
      +
      +
      +
      +
      +

      Return a new pass object which transforms invoke instructions into calls, +if the callee can not unwind the stack.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case pruneEH
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      This transformation attempts to discovery alloca allocations of aggregates that can be +broken down into component scalar values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case scalarReplacementOfAggregates
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + stripDeadPrototypes + +
      +
      +
      +
      +
      +
      +

      This pass removes any function declarations (prototypes) that are not used.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case stripDeadPrototypes
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + stripSymbols + +
      +
      +
      +
      +
      +
      +

      These functions removes symbols from functions and modules without +touching symbols for debugging information.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case stripSymbols
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + loopVectorize + +
      +
      +
      +
      +
      +
      +

      Performs a loop vectorization pass to widen instructions in loops to +operate on multiple consecutive iterations.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case loopVectorize
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + slpVectorize + +
      +
      +
      +
      +
      +
      +

      This pass performs a superword-level parallelism pass to combine +similar independent instructions into vector instructions.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case slpVectorize
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + invalid(reason:) + +
      +
      +
      +
      +
      +
      +

      An invalid pass that crashes when added to the pass manager.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case invalid(reason: String)
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Enums/RealPredicate.html b/docs/Enums/RealPredicate.html index 63546284..e62fee35 100644 --- a/docs/Enums/RealPredicate.html +++ b/docs/Enums/RealPredicate.html @@ -1,27 +1,35 @@ - RealPredicate Enum Reference + RealPredicate Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • @@ -396,23 +634,19 @@

      Declaration

      Declaration

      Swift

      -
      case orderedEqual
      +
      case orderedEqual
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    • - + - ordered + ordered
      @@ -582,23 +796,19 @@

      Declaration

      Declaration

      Swift

      -
      case ordered
      +
      case ordered
    - - -
    -
    • @@ -613,23 +823,19 @@

      Declaration

      Declaration

      Swift

      -
      case unordered
      +
      case unordered
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    • - + - true + true
      @@ -830,420 +1012,7 @@

      Declaration

      Declaration

      Swift

      -
      case `true`
      - -
      -
      - -
    - - - -
    -
      -
    • -
      - - - - llvm - -
      -
      -
      -
      -
      -
      -

      Retrieves the corresponding LLVMRealPredicate.

      - -
      -
      -

      Declaration

      -
      -

      Swift

      -
      public var llvm: LLVMRealPredicate
      - -
      -
      -
      -
      -
    • -
    -
    -
    -
    - diff --git a/docs/Enums/FloatType.html b/docs/Enums/RelocationModel.html similarity index 50% rename from docs/Enums/FloatType.html rename to docs/Enums/RelocationModel.html index 0e0e898c..1717e3ea 100644 --- a/docs/Enums/FloatType.html +++ b/docs/Enums/RelocationModel.html @@ -1,27 +1,35 @@ - FloatType Enum Reference + RelocationModel Enumeration Reference + + + - - + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    -
    -
    • - - - float + + + static
      @@ -390,30 +627,26 @@

      Declaration

      -

      32-bit floating point value

      +

      Generated code will exist at static offsets.

      Declaration

      Swift

      -
      case float
      +
      case `static`
    • -
    -
    -
    -
    • - - - double + + + pic
      @@ -421,30 +654,26 @@

      Declaration

      -

      64-bit floating point value

      +

      Generated code will be position-independent.

      Declaration

      Swift

      -
      case double
      +
      case pic
    • -
    -
    -
    -
    • - - - x86FP80 + + + dynamicNoPIC
      @@ -452,30 +681,27 @@

      Declaration

      -

      80-bit floating point value (X87)

      +

      Generated code will not be position-independent and may be used in static +or dynamic executables but not necessarily a shared library.

      Declaration

      Swift

      -
      case x86FP80
      +
      case dynamicNoPIC
    • -
    -
    -
    -
    • - - - fp128 + + + ropi
      @@ -483,30 +709,40 @@

      Declaration

      -

      128-bit floating point value (112-bit mantissa)

      +

      Generated code will be compiled in read-only position independent mode. +In this mode, all read-only data and functions are at a link-time constant +offset from the program counter.

      + +

      ROPI is not supported by all target architectures and calling conventions. +It is a particular feature of ARM targets, though.

      + +

      ROPI may be useful to avoid committing to compile-time constant locations +for code in memory. This may be useful in the following circumstances:

      + +
        +
      • Code is loaded dynamically.
      • +
      • Code is loaded into memory conditionally, or in an undefined order.
      • +
      • Code is mapped into different addresses during different executions.
      • +

      Declaration

      Swift

      -
      case fp128
      +
      case ropi
    • -
    -
    -
    -
    • - - - ppcFP128 + + + rwpi
      @@ -514,30 +750,37 @@

      Declaration

      -

      128-bit floating point value (two 64-bits)

      +

      Generated code will be compiled in read-write position independent mode. +In this mode, all writable data is at a link-time constant offset from the +static base register.

      + +

      RWPI is not supported by all target architectures and calling conventions. +It is a particular feature of ARM targets, though.

      + +

      RWPI may be useful to avoid committing to compile-time constant locations +for code in memory. This is particularly useful for data that must be +multiply instantiated for reentrant routines, as each thread executing a +reentrant routine will recieve its own copy of any data in +read-write segments.

      Declaration

      Swift

      -
      case ppcFP128
      +
      case rwpi
    • -
    -
    -
    -
    - - -
    -
    • @@ -401,23 +639,19 @@

      Declaration

      Declaration

      Swift

      -
      case dllImport
      +
      case dllImport
    - - -
    -
    • @@ -435,23 +669,19 @@

      Declaration

      Declaration

      Swift

      -
      case dllExport
      +
      case dllExport
    - - -
    -
    • - + - llvm + llvm
      @@ -466,7 +696,7 @@

      Declaration

      Declaration

      Swift

      -
      public var llvm: LLVMDLLStorageClass
      +
      public var llvm: LLVMDLLStorageClass { get }
      @@ -478,8 +708,8 @@

      Declaration

    diff --git a/docs/Enums/TargetMachineError.html b/docs/Enums/TargetMachineError.html index a33ebe33..3a216ce5 100644 --- a/docs/Enums/TargetMachineError.html +++ b/docs/Enums/TargetMachineError.html @@ -1,27 +1,35 @@ - TargetMachineError Enum Reference + TargetMachineError Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    - - -
    -
    • @@ -429,23 +663,19 @@

      Declaration

      Declaration

      Swift

      -
      case invalidTriple(String)
      +
      case invalidTriple(String)
    - - -
    -
    - - -
    -
    • @@ -492,7 +718,7 @@

      Declaration

      Declaration

      Swift

      -
      public var description: String
      +
      public var description: String { get }
      @@ -504,8 +730,8 @@

      Declaration

    diff --git a/docs/Enums/ThreadLocalModel.html b/docs/Enums/ThreadLocalModel.html index 304d82e4..33474dd0 100644 --- a/docs/Enums/ThreadLocalModel.html +++ b/docs/Enums/ThreadLocalModel.html @@ -1,27 +1,35 @@ - ThreadLocalModel Enum Reference + ThreadLocalModel Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • @@ -395,33 +648,41 @@

      Declaration

      -

      Allows reference of all thread-local variables, from either a shared -object or a dynamic executable. This model also supports the deferred -allocation of a block of thread-local storage when the block is first -referenced from a specific thread.

      +

      Allows reference of all thread-local variables, from either a shared +object or a dynamic executable. This model also supports the deferred +allocation of a block of thread-local storage when the block is first +referenced from a specific thread. Note that the linker is free to +optimize accesses using this model to one of the more specific models +below which may ultimately defeat lazy allocation of the TLS storagee +block.

      + +

      The code generated for this model does not assume that any information +about the module or variable offsets is known at link-time. Instead, the +exact value of these variables is computed by the dynamic linker at +runtime and passeed to __tls_get_addr in an architecture-specific way.

      + +

      If possible, this model should be avoided if one of the more specific +models applies out of concern for code size and application startup +performance.

      Declaration

      Swift

      -
      case generalDynamic
      +
      case generalDynamic
    • -
    -
    -
    -
    • @@ -429,38 +690,43 @@

      Declaration

      -

      This model is an optimization of the General Dynamic model. The compiler +

      This model is an optimization of the generalDynamic model. The compiler might determine that a variable is bound locally, or protected, within the -object being built. In this case, the compiler instructs the link-editor -to statically bind the dynamic tlsoffset and use this model.

      +object being built. In this case, the compiler instructs the linker +to statically bind the dynamic offset of the variable and use this model.

      + +

      This model provides a performance benefit over the General Dynamic model. +Only one call to __tls_get_addr is required per function, to determine +the starting address of the variable within the TLS block for its +parent module. Additional accesses can add an offset to this address +value for repeated accesses.

      -

      This model provides a performance benefit over the General Dynamic model. -Only one call to tls_get_addr() is required per function, to determine -the address of dtv0,m. The dynamic thread-local storage offset, bound at -link-edit time, is added to the dtv0,m address for each reference.

      +

      The optimization available over the generalDynamic model is defeated if +a variable is only ever accessed once, as its access would incur the +same __tls_get_addr call and the additional overhead of the offset +calculation.

      + +

      The linker cannot, in general, optimize from the general dynamic model +to the local dynamic model.

      Declaration

      Swift

      -
      case localDynamic
      +
      case localDynamic
    • -
    -
    -
    -
    • @@ -468,19 +734,19 @@

      Declaration

      -

      This model can only reference thread-local variables which are available -as part of the initial static thread-local template. This template is -composed of all thread-local storage blocks that are available at process -startup, plus a small backup reservation.

      +

      This model can only reference thread-local variables which are available +as part of the initial static thread-local template. This template is +composed of all thread-local storage blocks that are available at process +startup, plus a small backup reservation.

      In this model, the thread pointer-relative offset for a given variable x is stored in the GOT entry for x.

      -

      This model can reference a limited number of thread-local variables from +

      This model can reference a limited number of thread-local variables from shared libraries loaded after initial process startup, such as by means of -lazy loading, filters, or dlopen(). This access is satisfied from a -fixed backup reservation. This reservation can only provide storage for -uninitialized thread-local data items. For maximum flexibility, shared +lazy loading, filters, or dlopen(). This access is satisfied from a +fixed backup reservation. This reservation can only provide storage for +uninitialized thread-local data items. For maximum flexibility, shared objects should reference thread-local variables using a dynamic model of thread-local storage.

      @@ -489,23 +755,19 @@

      Declaration

      Declaration

      Swift

      -
      case initialExec
      +
      case initialExec
    • -
    -
    -
    -
    • @@ -513,11 +775,13 @@

      Declaration

      -

      This model can only reference thread-local variables which are part of the -thread-local storage block of the dynamic executable. The link-editor -calculates the thread pointer-relative offsets statically, without the -need for dynamic relocations, or the extra reference to the GOT. This -model can not be used to reference variables outside of the dynamic +

      This model is an optimization of the localDynamic model.

      + +

      This model can only reference thread-local variables which are part of the +thread-local storage block of the dynamic executable. The linker +calculates the thread pointer-relative offsets statically, without the +need for dynamic relocations, or the extra reference to the GOT. This +model can not be used to reference variables outside of the dynamic executable.

      @@ -525,23 +789,19 @@

      Declaration

      Declaration

      Swift

      -
      case localExec
      +
      case localExec
    - - -
    -
    • - + - llvm + llvm
      @@ -556,7 +816,7 @@

      Declaration

      Declaration

      Swift

      -
      public var llvm: LLVMThreadLocalMode
      +
      public var llvm: LLVMThreadLocalMode { get }
      @@ -568,8 +828,8 @@

      Declaration

    diff --git a/docs/Enums/UnnamedAddressKind.html b/docs/Enums/UnnamedAddressKind.html new file mode 100644 index 00000000..16d11271 --- /dev/null +++ b/docs/Enums/UnnamedAddressKind.html @@ -0,0 +1,699 @@ + + + + UnnamedAddressKind Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    UnnamedAddressKind

    +
    +
    + +
    public enum UnnamedAddressKind
    + +
    +
    +

    Enumerates values representing whether or not this global value’s address +is significant in this module or the program at large. A global value’s +address is considered significant if it is referenced by any module in the +final program.

    + +

    This attribute is intended to be used only by the code generator and LTO to +allow the linker to decide whether the global needs to be in the symbol +table. Constant global values with unnamed addresses and identical +initializers may be merged by LLVM. Note that a global value with an +unnamed address may be merged with a global value with a significant address +resulting in a global value with a significant address.

    + +
    +
    +
    +
      +
    • +
      + + + + none + +
      +
      +
      +
      +
      +
      +

      Indicates that the address of this global value is significant +in this module.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case none
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + local + +
      +
      +
      +
      +
      +
      +

      Indicates that the address of this global value is not significant to the +current module but it may or may not be significant to another module; +only the content of the value is known to be significant within the +current module.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case local
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + global + +
      +
      +
      +
      +
      +
      +

      Indicates that the address of this global value is not significant to the +current module or any other module; only the content of the value +is significant globally.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case global
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Enums/Visibility.html b/docs/Enums/Visibility.html index 2cdc1360..67f7a144 100644 --- a/docs/Enums/Visibility.html +++ b/docs/Enums/Visibility.html @@ -1,27 +1,35 @@ - Visibility Enum Reference + Visibility Enumeration Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - -
    -
    • - + - hidden + hidden
      @@ -404,23 +642,19 @@

      Declaration

      Declaration

      Swift

      -
      case hidden
      +
      case hidden
    - - -
    -
    • @@ -438,23 +672,19 @@

      Declaration

      Declaration

      Swift

      -
      case protected
      +
      case protected
    - - -
    -
    • - + - llvm + llvm
      @@ -469,7 +699,7 @@

      Declaration

      Declaration

      Swift

      -
      public var llvm: LLVMVisibility
      +
      public var llvm: LLVMVisibility { get }
      @@ -481,8 +711,8 @@

      Declaration

    diff --git a/docs/Extensions.html b/docs/Extensions.html index 45168c7d..46b73604 100644 --- a/docs/Extensions.html +++ b/docs/Extensions.html @@ -8,17 +8,26 @@ + + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -29,30 +38,93 @@
    @@ -395,9 +638,9 @@

    Declaration

  • - + - Int8 + Int8
    @@ -412,7 +655,7 @@

    Declaration

    Declaration

    Swift

    -
    struct Int8 : SignedInteger, Comparable, Equatable
    +
    extension Int8: IRValue
    @@ -422,9 +665,9 @@

    Declaration

  • - + - Int16 + Int16
    @@ -439,7 +682,7 @@

    Declaration

    Declaration

    Swift

    -
    struct Int16 : SignedInteger, Comparable, Equatable
    +
    extension Int16: IRValue
    @@ -449,9 +692,9 @@

    Declaration

  • - + - Int32 + Int32
    @@ -466,7 +709,7 @@

    Declaration

    Declaration

    Swift

    -
    struct Int32 : SignedInteger, Comparable, Equatable
    +
    extension Int32: IRValue
    @@ -476,9 +719,9 @@

    Declaration

  • - + - Int64 + Int64
    @@ -493,7 +736,7 @@

    Declaration

    Declaration

    Swift

    -
    struct Int64 : SignedInteger, Comparable, Equatable
    +
    extension Int64: IRValue
    @@ -520,7 +763,7 @@

    Declaration

    Declaration

    Swift

    -
    struct UInt : UnsignedInteger, Comparable, Equatable
    +
    extension UInt: IRValue
    @@ -530,9 +773,9 @@

    Declaration

  • - + - UInt8 + UInt8
    @@ -547,7 +790,7 @@

    Declaration

    Declaration

    Swift

    -
    struct UInt8 : UnsignedInteger, Comparable, Equatable
    +
    extension UInt8: IRValue
    @@ -557,9 +800,9 @@

    Declaration

  • - + - UInt16 + UInt16
    @@ -574,7 +817,7 @@

    Declaration

    Declaration

    Swift

    -
    struct UInt16 : UnsignedInteger, Comparable, Equatable
    +
    extension UInt16: IRValue
    @@ -584,9 +827,9 @@

    Declaration

  • - + - UInt32 + UInt32
    @@ -601,7 +844,7 @@

    Declaration

    Declaration

    Swift

    -
    struct UInt32 : UnsignedInteger, Comparable, Equatable
    +
    extension UInt32: IRValue
    @@ -611,9 +854,9 @@

    Declaration

  • - + - UInt64 + UInt64
    @@ -628,7 +871,7 @@

    Declaration

    Declaration

    Swift

    -
    struct UInt64 : UnsignedInteger, Comparable, Equatable
    +
    extension UInt64: IRValue
    @@ -655,7 +898,7 @@

    Declaration

    Declaration

    Swift

    -
    struct Bool
    +
    extension Bool: IRValue
    @@ -682,7 +925,7 @@

    Declaration

    Declaration

    Swift

    -
    struct String
    +
    extension String: IRValue
    @@ -694,8 +937,8 @@

    Declaration

    diff --git a/docs/Extensions/Bool.html b/docs/Extensions/Bool.html index 67258283..3460d78a 100644 --- a/docs/Extensions/Bool.html +++ b/docs/Extensions/Bool.html @@ -8,18 +8,26 @@ + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
  • - - -
    -
    • - + - IRValue + IRValue
      @@ -484,7 +980,7 @@

      Declaration

      Declaration

      Swift

      -
      public protocol IRValue
      +
      public protocol IRValue
      @@ -496,8 +992,8 @@

      Declaration

    diff --git a/docs/Protocols/Attribute.html b/docs/Protocols/Attribute.html new file mode 100644 index 00000000..96a1bb5b --- /dev/null +++ b/docs/Protocols/Attribute.html @@ -0,0 +1,634 @@ + + + + Attribute Protocol Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    Attribute

    +
    +
    + +
    public protocol Attribute
    + +
    +
    +

    An LLVM attribute.

    + +

    Functions, return types and each parameter may have a set of attributes +associated with them. Such attributes are used to communicate additional +information about a function. Attributes are considered to be part of the +function, but not of the function type.

    + +
    +
    +
    +
      +
    • +
      + + + + asLLVM() + +
      +
      +
      +
      +
      +
      +

      Retrieves the underlying LLVM attribute reference object.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      func asLLVM() -> LLVMAttributeRef
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Protocols/DIScope.html b/docs/Protocols/DIScope.html new file mode 100644 index 00000000..67b55dc2 --- /dev/null +++ b/docs/Protocols/DIScope.html @@ -0,0 +1,632 @@ + + + + DIScope Protocol Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    DIScope

    +
    +
    + +
    public protocol DIScope : IRMetadata
    + +
    +
    +

    Denotes a scope in which child metadata nodes can be inserted.

    + +
    +
    +
    +
      +
    • +
      + + + + file + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the file metadata associated with this scope, if any.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var file: FileMetadata? { get }
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Protocols/DIType.html b/docs/Protocols/DIType.html new file mode 100644 index 00000000..f5abc693 --- /dev/null +++ b/docs/Protocols/DIType.html @@ -0,0 +1,783 @@ + + + + DIType Protocol Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    DIType

    +
    +
    + +
    public protocol DIType : DIScope
    + +
    +
    +

    Denotes metadata for a type.

    + +
    +
    +
    +
      +
    • +
      + + + + name + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the name of this type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var name: String { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + sizeInBits + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the size of the type represented by this metadata in bits.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var sizeInBits: Size { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + offsetInBits + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the offset of the type represented by this metadata in bits.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var offsetInBits: Size { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + alignmentInBits + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the alignment of the type represented by this metadata in bits.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var alignmentInBits: Alignment { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + line + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the line the type represented by this metadata is declared on.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var line: Int { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + flags + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the flags the type represented by this metadata is declared +with.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var flags: DIFlags { get }
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Protocols/IRConstant.html b/docs/Protocols/IRConstant.html new file mode 100644 index 00000000..0132e571 --- /dev/null +++ b/docs/Protocols/IRConstant.html @@ -0,0 +1,714 @@ + + + + IRConstant Protocol Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    IRConstant

    +
    +
    + +
    public protocol IRConstant : IRValue
    + +
    +
    +

    An IRConstant is an entity whose value doees not change during the +runtime of a program. This includes global variables and functions, whose +addresses are constant, and constant expressions.

    + +
    +
    +
    +
      +
    • +
      + + + + constGEP(indices:) + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Perform a GEP (Get Element Pointer) with this value as the base.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func constGEP(indices: [IRConstant]) -> IRConstant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + indices + + +
      +

      A list of indices that indicate which of the elements +of the aggregate object are indexed.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing the address of a subelement of the given +aggregate data structure value.

      +
      +
      +
      +
    • +
    • +
      + + + + bitCast(to:) + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Build a constant bitcast to convert the given value to a value of the +given type by just copying the bit pattern.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func bitCast(to type: IRType) -> IRConstant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The destination type.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the result of bitcasting this +constant value to fit the given type.

      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Protocols/IRGlobal.html b/docs/Protocols/IRGlobal.html index e2769433..05088048 100644 --- a/docs/Protocols/IRGlobal.html +++ b/docs/Protocols/IRGlobal.html @@ -8,18 +8,26 @@ + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    + +
  • +
    + + + + unnamedAddressKind + + + Extension method + +
    +
    +
    +
    +
    +
    +

    Retrieves an indicator for the significance of a global value’s address.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var unnamedAddressKind: UnnamedAddressKind { get set }
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + comdat + + + Extension method + +
    +
    +
    +
    +
    +
    +

    Retrieves the COMDAT section for this global, if it exists.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var comdat: Comdat? { get set }
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + section + + + Extension method + +
    +
    +
    +
    +
    +
    +

    Retrieves the section associated with the symbol that will eventually be +emitted for this global value.

    +
    +

    Note

    + Global Alias values may or may not be resolvable to any +particular section given the state of the IR in an arbitrary module. A +return value of the empty string indicates a failed section lookup. + +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var section: String { get set }
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + guid + + + Extension method + +
    +
    +
    +
    +
    +
    +

    Retrieves a global unique identifier for this global value.

    + +

    This is a 64 bits hash that is used by PGO and ThinLTO to have a compact +unique way to identify a symbol.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var guid: UInt64 { get }
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + eraseFromParent() + + + Extension method + +
    +
    +
    +
    +
    +
    +

    Removes this global value from the module and deallocates it.

    +
    +

    Note

    +

    To ensure correct removal of the global value, you must invalidate + any references to it - usually by performing an + “Replace All Uses With” (RAUW) operation.

    + +
    +

    Warning

    +

    The native Swift object wrapping this global becomes a dangling + reference once this function has been invoked. It is + recommended that all references to it be dropped immediately.

    + +
    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func eraseFromParent()
    @@ -442,8 +1154,8 @@

    Declaration

    diff --git a/docs/Protocols/IRInstruction.html b/docs/Protocols/IRInstruction.html new file mode 100644 index 00000000..402f2048 --- /dev/null +++ b/docs/Protocols/IRInstruction.html @@ -0,0 +1,1005 @@ + + + + IRInstruction Protocol Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    IRInstruction

    +
    +
    + +
    public protocol IRInstruction : IRValue
    + +
    +
    +

    An IRInstruction is a value that directly represents an instruction and +in particular the result of the execution of that instruction.

    + +
    +
    +
    +
      +
    • +
      + + + + metadata + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves all metadata entries attached to this instruction.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var metadata: AttachedMetadata { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + addMetadata(_:kind:) + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Sets a metadata attachment, erasing the existing metadata attachment if +it already exists for the given kind.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func addMetadata(_ metadata: IRMetadata, kind: AttachedMetadata.PinnedKind)
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + metadata + + +
      +

      The metadata to attach to this global value.

      +
      +
      + + kind + + +
      +

      The kind of metadata to attach.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + addMetadata(_:kind:) + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Sets a metadata attachment, erasing the existing metadata attachment if +it already exists for the given kind.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func addMetadata(_ metadata: IRMetadata, kind: UInt32)
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + metadata + + +
      +

      The metadata to attach to this global value.

      +
      +
      + + kind + + +
      +

      The kind of metadata to attach.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + opCode + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the opcode associated with this Instruction.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var opCode: OpCode { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + debugLocation + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the current debug location of this instruction.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var debugLocation: DebugLocation? { get set }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + previous() + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Obtain the instruction that occurs before this one, if it exists.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func previous() -> Instruction?
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + next() + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Obtain the instruction that occurs after this one, if it exists.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func next() -> Instruction?
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + parentBlock + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the parent basic block that contains this instruction, if it +exists.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var parentBlock: BasicBlock? { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + firstUse + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the first use of this instruction.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var firstUse: Use? { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + uses + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Retrieves the sequence of instructions that use the value from this +instruction.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var uses: AnySequence<Use> { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + removeFromParent() + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Removes this instruction from a basic block but keeps it alive.

      +
      +

      Note

      + To ensure correct removal of the instruction, you must invalidate + any remaining references to its result values. + +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func removeFromParent()
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Protocols/IRMetadata.html b/docs/Protocols/IRMetadata.html new file mode 100644 index 00000000..e81ffa92 --- /dev/null +++ b/docs/Protocols/IRMetadata.html @@ -0,0 +1,808 @@ + + + + IRMetadata Protocol Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    IRMetadata

    +
    +
    + +
    public protocol IRMetadata : _IRMetadataInitializerHack
    + +
    +
    +

    The Metadata protocol captures those types that represent metadata nodes +in LLVM IR.

    + +

    LLVM IR allows metadata to be attached to instructions in the program that +can convey extra information about the code to the optimizers and code +generator. One example application of metadata is source-level debug +information.

    + +

    Metadata does not have a type, and is not a value. If referenced from a call +instruction, it uses the metadata type.

    +

    Debug Information

    + +

    The idea of LLVM debugging information is to capture how the important +pieces of the source-language’s Abstract Syntax Tree map onto LLVM code. +LLVM takes a number of positions on the impact of the broader compilation +process on debug information:

    + +
      +
    • Debugging information should have very little impact on the rest of the +compiler. No transformations, analyses, or code generators should need to +be modified because of debugging information.
    • +
    • LLVM optimizations should interact in well-defined and easily described +ways with the debugging information.
    • +
    • Because LLVM is designed to support arbitrary programming languages, +LLVM-to-LLVM tools should not need to know anything about the semantics +of the source-level-language.
    • +
    • Source-level languages are often widely different from one another. LLVM +should not put any restrictions of the flavor of the source-language, and +the debugging information should work with any language.
    • +
    • With code generator support, it should be possible to use an LLVM compiler +to compile a program to native machine code and standard debugging +formats. This allows compatibility with traditional machine-code level +debuggers, like GDB, DBX, or CodeView.
    • +
    + +
    +
    +
    +
      +
    • +
      + + + + asMetadata() + +
      +
      +
      +
      +
      +
      +

      Retrieves the underlying LLVM metadata object.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      func asMetadata() -> LLVMMetadataRef
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + replaceAllUses(with:) + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Replaces all uses of the this metadata with the given metadata.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func replaceAllUses(with metadata: IRMetadata)
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + metadata + + +
      +

      The new value to swap in.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + dump() + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Dumps a representation of this metadata to stderr.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func dump()
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + forceCast(to:) + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Force-casts metadata to a destination type.

      +
      +

      Warning

      + In general, use of this method is discouraged and can +lead to unpredictable results or undefined behavior. No checks are +performed before, during, or after the cast. + +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func forceCast<DestTy>(to: DestTy.Type) -> DestTy where DestTy : IRMetadata
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + kind + + + Extension method + +
      +
      +
      +
      +
      +
      +

      Returns the kind of this metadata node.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var kind: IRMetadataKind { get }
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Protocols/IRType.html b/docs/Protocols/IRType.html index 988222df..79f9e99a 100644 --- a/docs/Protocols/IRType.html +++ b/docs/Protocols/IRType.html @@ -8,18 +8,26 @@ + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
  • +
  • +
    + + + + context + + + Extension method + +
    +
    +
    +
    +
    +
    +

    Returns the context associated with this type

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    var context: Context { get }
    @@ -475,9 +743,9 @@

    Declaration

  • - - - dump() + + + scalarType Extension method @@ -488,14 +756,15 @@

    Declaration

    -

    Dumps a representation of this type to stderr.

    +

    If this is a vector type, return the element type, otherwise +return self.

    Declaration

    Swift

    -
    public func dump()
    +
    var scalarType: IRType { get }
    @@ -507,8 +776,8 @@

    Declaration

  • diff --git a/docs/Protocols/IRValue.html b/docs/Protocols/IRValue.html index 87ce1429..cc78f2ce 100644 --- a/docs/Protocols/IRValue.html +++ b/docs/Protocols/IRValue.html @@ -8,18 +8,26 @@ + + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
  • - - -
    -
    + diff --git a/docs/Structs.html b/docs/Structs.html index 4752c8ed..265726ba 100644 --- a/docs/Structs.html +++ b/docs/Structs.html @@ -1,26 +1,35 @@ - Structs Reference + Structures Reference + + + - + +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -29,30 +38,93 @@
    + +
  • +
    + + + + APInt + +
    +
    +
    +
    +
    +
    +

    A value implementing arbitrary precision integer arithmetic.

    + +

    APInt is a functional replacement for common case unsigned integer type +like UInt or UInt64, but also allows non-byte-width +integer sizes and large integer value types such as 3-bits, 15-bits, or more +than 64-bits of precision. APInt provides a variety of arithmetic +operators and methods to manipulate integer values of any bit-width. It +supports both the typical integer arithmetic and comparison operations as +well as bitwise manipulation.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct APInt : IRConstant
    +
    extension APInt: Comparable
    +
    extension APInt: Numeric
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + ArrayType + +
    +
    +
    +
    +
    +
    +

    ArrayType is a very simple derived type that arranges elements +sequentially in memory. ArrayType requires a size (number of elements) and +an underlying data type.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct ArrayType : IRType
    +
    extension ArrayType: Equatable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + BasicBlock + +
    +
    +
    +
    +
    +
    +

    A BasicBlock represents a basic block in an LLVM IR program. A basic +block contains a sequence of instructions, a pointer to its parent block and +its follower block, and an optional label that gives the basic block an +entry in the symbol table. Because of this label, the type of every basic +block is LabelType.

    + +

    A basic block can be thought of as a sequence of instructions, and indeed +its member instructions may be iterated over with a for-in loop. A well- +formed basic block has as its last instruction a “terminator” that produces +a transfer of control flow and possibly yields a value. All other +instructions in the middle of the basic block may not be “terminator” +instructions. Basic blocks are not required to be well-formed until +code generation is complete.

    +

    Creating a Basic Block

    + +

    By default, the initializer for a basic block merely creates the block but +does not associate it with a function.

    +
    let module = Module(name: "Example")
    +let fun = builder.addFunction("example",
    +                              type: FunctionType([], VoidType()))
    +
    +// This basic block is "floating" outside of a function.
    +let floatingBB = BasicBlock(name: "floating")
    +// Until we associate it with a function by calling `Function.append(_:)`.
    +fun.append(floatingBB)
    +
    + +

    A basic block may be created and automatically inserted at the end of a +function by calling Function.appendBasicBlock(named:in:).

    +
    let module = Module(name: "Example")
    +let fun = builder.addFunction("example",
    +                              type: FunctionType([], VoidType()))
    +
    +// This basic block is "attached" to the example function.
    +let attachedBB = fun.appendBasicBlock(named: "attached")
    +
    +

    The Address of a Basic Block

    + +

    Basic blocks (except the entry block) may have their labels appear in the +symbol table. Naturally, these labels are associated with address values +in the final object file. The value of that address may be accessed for the +purpose of an indirect call or a direct comparisson by calling +Function.address(of:) and providing one of the function’s child blocks as +an argument. Providing any other basic block outside of the function as an +argument value is undefined.

    +

    The Entry Block

    + +

    The first basic block (the entry block) in a Function is special:

    + +
      +
    • The entry block is immediately executed when the flow of control enters +its parent function.
    • +
    • The entry block is not allowed to have predecessor basic blocks +(i.e. there cannot be any branches to the entry block of a function).
    • +
    • The address of the entry block is not a well-defined value.
    • +
    • The entry block cannot have PHI nodes. This is enforced structurally, +as the entry block can have no predecessor blocks to serve as operands +to the PHI node.
    • +
    • Static alloca instructions situated in the entry block are treated +specially by most LLVM backends. For example, FastISel keeps track of +static alloca values in the entry block to more efficiently reference +them from the base pointer of the stack frame.
    • +
    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct BasicBlock : IRValue
    +
    extension BasicBlock: Equatable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Call + +
    +
    +
    +
    +
    +
    +

    Represents a simple function call.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct Call : IRInstruction
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Invoke + +
    +
    +
    +
    +
    +
    +

    Represents a function call that may transfer control to an exception handler.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct Invoke : IRInstruction
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Constant + +
    +
    +
    +
    +
    +
    +

    A Constant represents a value initialized to a constant. Constant values +may be manipulated with standard Swift arithmetic operations and used with +standard IR Builder instructions like any other operand. The difference +being any instructions acting solely on constants and any arithmetic +performed on constants is evaluated at compile-time only.

    + +

    Constants keep track of the values they represent at the type level to +disallow mixed-type arithmetic. Use the cast family of operations to +safely convert constants to other representations.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct Constant<Repr> : IRConstant where Repr : ConstantRepresentation
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + FloatType + +
    +
    +
    +
    +
    +
    +

    FloatType enumerates representations of a floating value of a particular +bit width and semantics.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct FloatType : IRType
    +
    extension FloatType: Equatable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + EnumAttribute + +
    +
    +
    +
    +
    +
    +

    An “enum” (a.k.a. target-independent) attribute.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct EnumAttribute : Attribute
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + StringAttribute + +
    +
    +
    +
    +
    +
    +

    A “string” (a.k.a. target-dependent) attribute.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct StringAttribute : Attribute
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Parameter + +
    +
    +
    +
    +
    +
    +

    A Parameter represents an index into the parameters of a Function.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct Parameter : IRValue
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + FunctionType + +
    +
    +
    +
    +
    +
    +

    FunctionType represents a function’s type signature. It consists of a +return type and a list of formal parameter types. The return type of a +function type is a void type or first class type — except for LabelType +and MetadataType.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct FunctionType : IRType
    +
    extension FunctionType: Equatable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + DebugLocation + +
    +
    +
    +
    +
    +
    +

    A DebugLocation represents a location in source.

    + +

    Debug locations are de-duplicated by file and line. If more than one +location inside a given scope needs to share a line, a discriminator value +must be set or those locations will be considered equivalent.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct DebugLocation : IRMetadata
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + CompileUnitMetadata + +
    +
    +
    +
    +
    +
    +

    CompileUnitMetadata nodes represent a compile unit, the root of a metadata +hierarchy for a translation unit.

    + +

    Compile unit descriptors provide the root scope for objects declared in a +specific compilation unit. FileMetadata descriptors are defined using this +scope.

    + +

    These descriptors are collected by a named metadata node !llvm.dbg.cu. +They keep track of global variables, type information, and imported entities +(declarations and namespaces).

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct CompileUnitMetadata : DIScope
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + FileMetadata + +
    +
    +
    +
    +
    +
    +

    FileMetadata nodes represent files.

    + +

    The file name does not necessarily have to be a proper file path. For +example, it can include additional slash-separated path components.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct FileMetadata : DIScope
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + DIBasicType + +
    +
    +
    +
    +
    +
    +

    DIBasicType nodes represent primitive types, such as int, bool and +float.

    + +

    Basic types carry an encoding describing the details of the type to +influence how it is presented in debuggers. LLVM currently supports +specific DWARF “Attribute Type Encodings” that are enumerated in +DIAttributeTypeEncoding.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct DIBasicType : DIType
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + DISubroutineType + +
    +
    +
    +
    +
    +
    +

    DISubroutineType nodes represent subroutine types.

    + +

    Subroutine types are meant to mirror their formal declarations in source: +arguments are represented in order. The return type is optional and meant +to represent the concept of void in C-like languages.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct DISubroutineType : DIType
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + LexicalBlockMetadata + +
    +
    +
    +
    +
    +
    +

    LexicalBlockMetadata nodes describe nested blocks within a subprogram. The +line number and column numbers are used to distinguish two lexical blocks at +same depth.

    + +

    Usually lexical blocks are distinct to prevent node merging based on +operands.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct LexicalBlockMetadata : DIScope
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    LexicalBlockFile nodes are used to discriminate between sections of a +lexical block. The file field can be changed to indicate textual inclusion, +or the discriminator field can be used to discriminate between control flow +within a single block in the source language.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct LexicalBlockFileMetadata : DIScope
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + LocalVariableMetadata + +
    +
    +
    +
    +
    +
    +

    LocalVariableMetadata nodes represent local variables and function +parameters in the source language.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct LocalVariableMetadata : IRMetadata
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    ObjectiveCPropertyMetadata nodes represent Objective-C property nodes.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct ObjectiveCPropertyMetadata : IRMetadata
    + +
    +
    +
    +
    +
  • +
  • + +
    +
    +
    +
    +
    +

    ImportedEntityMetadata nodes represent entities (such as modules) imported +into a compile unit.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct ImportedEntityMetadata : DIType
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + FunctionMetadata + +
    +
    +
    +
    +
    +
    +

    NameSpaceMetadata nodes represent subroutines in the source program. +They are attached to corresponding LLVM IR functions.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct FunctionMetadata : DIScope
  • - - -
    -
    • @@ -384,33 +1469,27 @@

      Declaration

      -

      ArrayType is a very simple derived type that arranges elements -sequentially in memory. ArrayType requires a size (number of elements) and -an underlying data type.

      +

      NameSpaceMetadata nodes represent entities like C++ modules.

      - See more + See more

      Declaration

      Swift

      -
      public struct ArrayType: IRType
      +
      public struct ModuleMetadata : DIScope
    • -
    -
    -
    -
    • @@ -418,43 +1497,27 @@

      Declaration

      -

      A BasicBlock represents a basic block in an LLVM IR program. A basic -block contains a sequence of instructions, a pointer to its parent block and -its follower block, and an optional label that gives the basic block an -entry in the symbol table.

      - -

      A basic block can be thought of as a sequence of instructions, and indeed -its member instructions may be iterated over with a for-in loop.

      +

      NameSpaceMetadata nodes represent entities like C++ namespaces.

      -

      The first basic block in a function is special in two ways: it is -immediately executed on entrance to the function, and it is not allowed to -have predecessor basic blocks (i.e. there can not be any branches to the -entry block of a function). Because the block can have no predecessors, it -also cannot have any PHI nodes.

      - - See more + See more

      Declaration

      Swift

      -
      public struct BasicBlock: IRValue
      +
      public struct NameSpaceMetadata : DIScope
    • -
    -
    -
    -
    • - - - Call + + + MDString
      @@ -462,15 +1525,15 @@

      Declaration

      -

      Represents a simple function call.

      +

      MDString nodes represent string constants in metadata nodes.

      - See more + See more

      Declaration

      Swift

      -
      public struct Call: IRValue
      +
      public struct MDString : IRMetadata, ExpressibleByStringLiteral
      @@ -480,9 +1543,9 @@

      Declaration

    • - - - Invoke + + + MDNode
      @@ -490,31 +1553,31 @@

      Declaration

      -

      Represents a function call that may transfer control to an exception handler.

      +

      MDNode objects represent generic nodes in a metadata graph.

      - See more +

      A metadata node is a tuple of references to other metadata. In general, +metadata graphs are acyclic and terminate in metadata nodes without +operands.

      + + See more

      Declaration

      Swift

      -
      public struct Invoke: IRValue
      +
      public struct MDNode : IRMetadata
    • -
    -
    -
    -
    • @@ -522,39 +1585,38 @@

      Declaration

      -

      A Constant represents a value initialized to a constant. Constant values -may be manipulated with standard Swift arithmetic operations and used with -standard IR Builder instructions like any other operand. The difference -being any instructions acting solely on constants and any arithmetic -performed on constants is evaluated at compile-time only.

      +

      ExpressionMetadata nodes represent expressions that are inspired by the +DWARF expression language. They are used in debug intrinsics (such as +llvm.dbg.declare and llvm.dbg.value) to describe how the referenced LLVM +variable relates to the source language variable.

      -

      Constants keep track of the values they represent at the type level to -disallow mixed-type arithmetic. Use the cast family of operations to -safely convert constants to other representations.

      +

      Debug intrinsics are interpreted left-to-right: start by pushing the +value/address operand of the intrinsic onto a stack, then repeatedly push +and evaluate opcodes from the ExpressionMetadata until the final variable +description is produced.

      - See more +

      Though DWARF supports hundreds of expressions, LLVM currently implements +a very limited subset.

      + + See more

      Declaration

      Swift

      -
      public struct Constant<Repr: ConstantRepresentation>: IRValue
      +
      public struct ExpressionMetadata : IRMetadata
    • -
    -
    -
    -
    • - - - Parameter + + + Instruction
      @@ -562,31 +1624,27 @@

      Declaration

      -

      A Parameter represents an index into the parameters of a Function.

      +

      An Instruction represents an instruction residing in a basic block.

      - See more + See more

      Declaration

      Swift

      -
      public struct Parameter: IRValue
      +
      public struct Instruction : IRInstruction
    • -
    -
    -
    -
    • @@ -594,34 +1652,28 @@

      Declaration

      -

      FunctionType represents a function’s type signature. It consists of a -return type and a list of formal parameter types. The return type of a -function type is a void type or first class type — except for LabelType -and MetadataType.

      +

      A TerminatorInstruction represents an instruction that terminates a +basic block.

      - See more + See more

      Declaration

      Swift

      -
      public struct FunctionType: IRType
      +
      public struct TerminatorInstruction : IRInstruction
    • -
    -
    -
    -
    • - - - Global + + + IntType
      @@ -629,33 +1681,32 @@

      Declaration

      -

      A Global represents a region of memory allocated at compile time instead -of at runtime. A global variable must either have an initializer, or make -reference to an external definition that has an initializer.

      +

      The IntType represents an integral value of a specified bit width.

      + +

      The IntType is a very simple type that simply specifies an arbitrary bit +width for the integer type desired. Any bit width from 1 bit to (2^23)-1 +(about 8 million) can be specified.

      - See more + See more

      Declaration

      Swift

      -
      public struct Global: IRGlobal
      +
      public struct IntType : IRType
      +
      extension IntType: Equatable
    • -
    -
    -
    -
    • - - - Instruction + + + LabelType
      @@ -663,27 +1714,41 @@

      Declaration

      -

      An Instruction represents an instruction residing in a basic block.

      +

      LabelType represents code labels.

      - See more + See more

      Declaration

      Swift

      -
      public struct Instruction: IRValue
      +
      public struct LabelType : IRType
      +
      extension LabelType: Equatable
    • +
    +
    +
    +
    + + +
    + +

    TBAA Metadata

    +

    +
    +
    +
    • @@ -691,32 +1756,27 @@

      Declaration

      -

      A TerminatorInstruction represents an instruction that terminates a -basic block.

      +

      Represents a single field in a (C or C++) struct.

      - See more + See more

      Declaration

      Swift

      -
      public struct TerminatorInstruction
      +
      public struct TBAAStructField
    • -
    -
    -
    -
    • @@ -724,35 +1784,27 @@

      Declaration

      -

      The IntType represents an integral value of a specified bit width.

      - -

      The IntType is a very simple type that simply specifies an arbitrary bit -width for the integer type desired. Any bit width from 1 bit to (2^23)-1 -(about 8 million) can be specified.

      +

      Enumerates the known attributes that can appear on an Objective-C property.

      - See more + See more

      Declaration

      Swift

      -
      public struct IntType: IRType
      +
      public struct ObjectiveCPropertyAttribute : OptionSet
    • -
    -
    -
    -
    • - - - LabelType + + + DIFlags
      @@ -760,31 +1812,29 @@

      Declaration

      -

      LabelType represents code labels.

      +

      Enumerates a set of flags that can be applied to metadata nodes to change +their interpretation at compile time or attach additional semantic +significance at runtime.

      - See more + See more

      Declaration

      Swift

      -
      public struct LabelType: IRType
      +
      public struct DIFlags : OptionSet
    • -
    -
    -
    -
    • @@ -801,23 +1851,20 @@

      Declaration

      Declaration

      Swift

      -
      public struct MetadataType: IRType
      +
      public struct MetadataType : IRType
      +
      extension MetadataType: Equatable
    - - -
    -
    • - + - Section + Section
      @@ -833,7 +1880,7 @@

      Declaration

      Declaration

      Swift

      -
      public struct Section
      +
      public struct Section
      @@ -843,9 +1890,9 @@

      Declaration

    • - + - Symbol + Symbol
      @@ -861,7 +1908,7 @@

      Declaration

      Declaration

      Swift

      -
      public struct Symbol
      +
      public struct Symbol
      @@ -871,9 +1918,9 @@

      Declaration

    • @@ -890,23 +1937,19 @@

      Declaration

      Declaration

      Swift

      -
      public struct Relocation
      +
      public struct Relocation
    - - -
    -
    - - -
    -
    • @@ -988,23 +2027,20 @@

      Declaration

      Declaration

      Swift

      -
      public struct PointerType: IRType
      +
      public struct PointerType : IRType
      +
      extension PointerType: Equatable
    - - -
    -
    • @@ -1020,13 +2056,13 @@

      Declaration

      registers are accessed using the extractvalue and insertvalue instructions.

      -

      Structures may optionally be packed structures, which indicate that the +

      Structures may optionally be “packed” structures, which indicate that the alignment of the struct is one byte, and that there is no padding between the elements. In non-packed structs, padding between field types is inserted as defined by the DataLayout of the module, which is required to match what the underlying code generator expects.

      -

      Structures can either be literal or identified. A literal structure is +

      Structures can either be “literal” or “identified”. A literal structure is defined inline with other types (e.g. {i32, i32}*) whereas identified types are always defined at the top level with a name. Literal types are uniqued by their contents and can never be recursive or opaque since there is no way @@ -1039,23 +2075,20 @@

      Declaration

      Declaration

      Swift

      -
      public struct StructType: IRType
      +
      public struct StructType : IRType
      +
      extension StructType: Equatable
    - - -
    -
    + +
  • +
    + + + + StructLayout + +
    +
    +
    +
    +
    +
    +

    A StructLayout encapsulates information about the layout of a StructType.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct StructLayout
  • - - -
    -
    • @@ -1108,23 +2165,135 @@

      Declaration

      Declaration

      Swift

      -
      public struct TokenType: IRType
      +
      public struct TokenType : IRType
      +
      extension TokenType: Equatable
      + +
      +
      + +
    + +
  • +
    + + + + Triple + +
    +
    +
    +
    +
    +
    +

    A Triple provides an abstraction over “Target Triples”.

    + +

    A Target Triple encodes information about the target of a +compilation session including the underlying processor architecture, OS, +platform vendor, and additional information about the runtime environment.

    + +

    A target triple is usually specified at the command line as a - delimited +string in the format:

    +
    <arch><sub>-<vendor>-<sys>-<abi>
    +
    + +

    For example:

    +
    nvptx64-nvidia-cuda
    +x86_64-unknown-linux-gnu
    +x86_64-apple-ios8.3-simulator
    +
    + +

    For this reason, Triple provides an initializer that parses strings in +this format.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct Triple : Equatable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Alignment + +
    +
    +
    +
    +
    +
    +

    An alignment value, expressed in bytes.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct Alignment : Comparable, Hashable
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + Size + +
    +
    +
    +
    +
    +
    +

    This is an opaque type for sizes expressed in aggregate bit units, usually 8 +bits per unit.

    + +

    Instances of this type represent a quantity as a multiple of a radix size

    + +
      +
    • e.g. the size of a char in bits on the target architecture. As an opaque +type, Size protects you from accidentally combining operations on +quantities in bit units and size units.
    • +
    + +

    For portability, never assume that a target radix is 8 bits wide. Use +Size values wherever you calculate sizes and offsets.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public struct Size
    +
    extension Size: UnsignedInteger
  • - - -
    -
    • - + - Use + Use
      @@ -1141,23 +2310,19 @@

      Declaration

      Declaration

      Swift

      -
      public struct Use
      +
      public struct Use
    - - -
    -
    • @@ -1176,23 +2341,20 @@

      Declaration

      Declaration

      Swift

      -
      public struct VectorType: IRType
      +
      public struct VectorType : IRType
      +
      extension VectorType: Equatable
    - - -
    -
    • - + - VoidType + VoidType
      @@ -1208,23 +2370,20 @@

      Declaration

      Declaration

      Swift

      -
      public struct VoidType: IRType
      +
      public struct VoidType : IRType
      +
      extension VoidType: Equatable
    - - -
    -
    • @@ -1245,7 +2404,8 @@

      Declaration

      Declaration

      Swift

      -
      public struct X86MMXType: IRType
      +
      public struct X86MMXType : IRType
      +
      extension X86MMXType: Equatable
      @@ -1257,8 +2417,8 @@

      Declaration

    diff --git a/docs/Structs/APInt.html b/docs/Structs/APInt.html new file mode 100644 index 00000000..427ceaf7 --- /dev/null +++ b/docs/Structs/APInt.html @@ -0,0 +1,2582 @@ + + + + APInt Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    APInt

    +
    +
    + +
    public struct APInt : IRConstant
    +
    extension APInt: Comparable
    +
    extension APInt: Numeric
    + +
    +
    +

    A value implementing arbitrary precision integer arithmetic.

    + +

    APInt is a functional replacement for common case unsigned integer type +like UInt or UInt64, but also allows non-byte-width +integer sizes and large integer value types such as 3-bits, 15-bits, or more +than 64-bits of precision. APInt provides a variety of arithmetic +operators and methods to manipulate integer values of any bit-width. It +supports both the typical integer arithmetic and comparison operations as +well as bitwise manipulation.

    + +
    +
    +
    +
      +
    • +
      + + + + Word + +
      +
      +
      +
      +
      +
      +

      The underlying word size.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public typealias Word = UInt64
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + bitWidth + +
      +
      +
      +
      +
      +
      +

      The bitwidth of this integer.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public private(set) var bitWidth: Int { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + asLLVM() + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func asLLVM() -> LLVMValueRef
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init() + +
      +
      +
      +
      +
      +
      +

      Creates and initializes a new APInt with a bitwidth of one and a value +of zero.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init()
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Creates and initializes a new APInt with a given bit width, value, and +signedness.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(width numBits: Int, value: UInt64, signed: Bool = false)
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + numBits + + +
      +

      The bit width of the integer.

      +
      +
      + + value + + +
      +

      The value of the integer.

      +
      +
      + + signed + + +
      +

      If true, treat the most significant bit at the given bit + width as a sign bit. Defaults to false.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + init(width:values:) + +
      +
      +
      +
      +
      +
      +

      Creates and initializes a new APInt with a given bit width and an +array of word values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(width numBits: Int, values: [Word])
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + numBits + + +
      +

      The bit width of the integer.

      +
      +
      + + values + + +
      +

      An array of words to form the value of the integer.

      +
      +
      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Comparisons

    +

    +
    +
    +
      +
    • +
      + + + + ==(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func == (lhs: APInt, rhs: APInt) -> Bool
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + <(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func < (lhs: APInt, rhs: APInt) -> Bool
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Arithmetic Operations

    +

    +
    +
    +
      +
    • +
      + + + + Magnitude + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public typealias Magnitude = APInt
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + IntegerLiteralType + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public typealias IntegerLiteralType = UInt64
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(integerLiteral:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(integerLiteral value: UInt64)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(exactly:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init?<T>(exactly source: T) where T : BinaryInteger
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + &(_:_:) + +
      +
      +
      +
      +
      +
      +

      Returns the result of performing a bitwise AND operation on the two +given values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func & (lhs: APInt, rhs: APInt) -> APInt
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + &=(_:_:) + +
      +
      +
      +
      +
      +
      +

      Stores the result of performing a bitwise AND operation on the two given +values in the left-hand-side variable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func &= (lhs: inout APInt, rhs: APInt)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + |(_:_:) + +
      +
      +
      +
      +
      +
      +

      Returns the result of performing a bitwise OR operation on the two +given values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func | (lhs: APInt, rhs: APInt) -> APInt
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + |=(_:_:) + +
      +
      +
      +
      +
      +
      +

      Stores the result of performing a bitwise OR operation on the two given +values in the left-hand-side variable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func |= (lhs: inout APInt, rhs: APInt)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ^(_:_:) + +
      +
      +
      +
      +
      +
      +

      Returns the result of performing a bitwise XOR operation on the two +given values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func ^ (lhs: APInt, rhs: APInt) -> APInt
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ^=(_:_:) + +
      +
      +
      +
      +
      +
      +

      Stores the result of performing a bitwise XOR operation on the two given +values in the left-hand-side variable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func ^= (lhs: inout APInt, rhs: APInt)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + +(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func + (lhs: APInt, rhs: APInt) -> APInt
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + +=(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func += (lhs: inout APInt, rhs: APInt)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + -(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func - (lhs: APInt, rhs: APInt) -> APInt
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + -=(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func -= (lhs: inout APInt, rhs: APInt)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + magnitude + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var magnitude: APInt { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + *(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func * (lhs: APInt, rhs: APInt) -> APInt
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + *=(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func *= (lhs: inout APInt, rhs: APInt)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + <<(_:_:) + +
      +
      +
      +
      +
      +
      +

      Returns the result of shifting a value’s binary representation the +specified number of digits to the left.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func << (lhs: APInt, amount: UInt64) -> APInt
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + <<=(_:_:) + +
      +
      +
      +
      +
      +
      +

      Stores the result of shifting a value’s binary representation the +specified number of digits to the left in the left-hand-side variable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func <<= (lhs: inout APInt, amount: UInt64)
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Logically shift the value right by the given amount.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func logicallyShiftedRight(by amount: UInt64) -> APInt
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + amount + + +
      +

      The amount to shift right by.

      +
      +
      +
      +
      +

      Return Value

      +

      An integer of the same bit width that has been logically + right shifted.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Logically shift the value right by the given amount.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func logicallyShiftRight(by amount: UInt64)
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + amount + + +
      +

      The amount to shift right by.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + zeroExtendedValue + +
      +
      +
      +
      +
      +
      +

      Attempts to return the value of this integer as a 64-bit unsigned integer +that has been zero-extended. If the value cannot be represented +faithfully in 64 bits, the result is nil.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var zeroExtendedValue: UInt64? { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + signExtendedValue + +
      +
      +
      +
      +
      +
      +

      Attempts to return the value of this integer as a 64-bit signed integer +that has been sign-extended. If the value cannot be rerprresented +faithfully in 64 bits, the result is nil.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var signExtendedValue: Int64? { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + isNegative + +
      +
      +
      +
      +
      +
      +

      Returns true if the most significant bit of this value is set.

      + +

      Note: This may return true even if you did not explicitly construct + a signed APInt.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var isNegative: Bool { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + areAllBitsSet + +
      +
      +
      +
      +
      +
      +

      Returns true if all bits are ones.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var areAllBitsSet: Bool { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + leadingZeroBitCount + +
      +
      +
      +
      +
      +
      +

      The number of leading zeros in this value’s binary representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var leadingZeroBitCount: Int { get }
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      The number of leading ones in this value’s binary representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var leadingNonZeroBitCount: Int { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + trailingZeroBitCount + +
      +
      +
      +
      +
      +
      +

      The number of trailing zeros in this value’s binary representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var trailingZeroBitCount: Int { get }
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      The number of trailing ones in this value’s binary representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var trailingNonZeroBitCount: Int { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + nonzeroBitCount + +
      +
      +
      +
      +
      +
      +

      The number of bits equal to 1 in this value’s binary representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var nonzeroBitCount: Int { get }
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Bit Twiddling Operations

    +

    +
    +
    +
      +
    • +
      + + + + setAllBits() + +
      +
      +
      +
      +
      +
      +

      Sets all bits to one in this value’s binary representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func setAllBits()
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + setBit(at:) + +
      +
      +
      +
      +
      +
      +

      Sets the bit at the given position to one.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func setBit(at position: Int)
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + position + + +
      +

      The position of the bit to set.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + setSignBit() + +
      +
      +
      +
      +
      +
      +

      Sets the sign bit to one in this value’s binary representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func setSignBit()
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + setBits(_:) + +
      +
      +
      +
      +
      +
      +

      Sets all bits in the given range to one in this value’s binary +representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func setBits(_ range: ClosedRange<Int>)
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + range + + +
      +

      The range of bits to flip.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + setBits(_:) + +
      +
      +
      +
      +
      +
      +

      Sets all bits in the given range to one in this value’s binary +representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func setBits(_ range: Range<Int>)
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + range + + +
      +

      The range of bits to flip.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + setBits(_:) + +
      +
      +
      +
      +
      +
      +

      Sets all bits in the given range to one in this value’s binary +representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func setBits(_ range: PartialRangeUpTo<Int>)
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + range + + +
      +

      The range of bits to flip.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + setBits(_:) + +
      +
      +
      +
      +
      +
      +

      Sets all bits in the given range to one in this value’s binary +representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func setBits(_ range: PartialRangeThrough<Int>)
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + range + + +
      +

      The range of bits to flip.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + setBits(_:) + +
      +
      +
      +
      +
      +
      +

      Sets all bits in the given range to one in this value’s binary +representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func setBits(_ range: PartialRangeFrom<Int>)
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + range + + +
      +

      The range of bits to flip.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + clearAllBits() + +
      +
      +
      +
      +
      +
      +

      Clears all bits to one in this value’s binary representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func clearAllBits()
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + clearBit(_:) + +
      +
      +
      +
      +
      +
      +

      Sets the bit at the given position to zero.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func clearBit(_ position: Int)
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + position + + +
      +

      The position of the bit to zero.

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + clearSignBit() + +
      +
      +
      +
      +
      +
      +

      Clears the sign bit in this value’s binary representation.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func clearSignBit()
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + truncate(to:) + +
      +
      +
      +
      +
      +
      +

      Truncates the integer to a given bit width.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func truncate(to width: Int) -> APInt
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + width + + +
      +

      The new width to truncate towards. This width cannot + exceed the current width of the integer.

      +
      +
      +
      +
      +

      Return Value

      +

      An integer of the given bit width that has been truncated.

      +
      +
      +
      +
    • +
    • +
      + + + + zeroExtend(to:) + +
      +
      +
      +
      +
      +
      +

      Zero extends the integer to a given bit width.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func zeroExtend(to width: Int) -> APInt
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + width + + +
      +

      The width to zero-extend the integer to. This value + may not be smaller than the current width of the + integer.

      +
      +
      +
      +
      +

      Return Value

      +

      An integer of the given bit width that has been zero-extended.

      +
      +
      +
      +
    • +
    • +
      + + + + signExtend(to:) + +
      +
      +
      +
      +
      +
      +

      Sign extends the integer to a given bit width.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func signExtend(to width: Int) -> APInt
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + width + + +
      +

      The width to sign-extend the integer to. This value + may not be smaller than the current width of the + integer.

      +
      +
      +
      +
      +

      Return Value

      +

      An integer of the given bit width that has been zero-extended.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Zero extends or truncates the integer to the given width.

      + +

      If the given bit width exceeds the current bit width, the value is +zero-extended. Else if the given bit width is less than the current +bit width, the value is truncated.

      + +

      If the given bit width matches the current bit width, this operation is +a no-op.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func zeroExtendOrTruncate(to width: Int) -> APInt
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + width + + +
      +

      The width to zero extend or truncate to.

      +
      +
      +
      +
      +

      Return Value

      +

      An integer that has been zero extended or truncated to fit + the given bit width.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Sign extends or truncates the integer to the given width.

      + +

      If the given bit width exceeds the current bit width, the value is +sign-extended. Else if the given bit width is less than the current +bit width, the value is truncated.

      + +

      If the given bit width matches the current bit width, this operation is +a no-op.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func signExtendOrTruncate(to width: Int) -> APInt
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + width + + +
      +

      The width to sign extend or truncate to.

      +
      +
      +
      +
      +

      Return Value

      +

      An integer that has been sign extended or truncated to fit + the given bit width.

      +
      +
      +
      +
    • +
    • +
      + + + + flipAll() + +
      +
      +
      +
      +
      +
      +

      Toggle every bit in this integer to its opposite value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public mutating func flipAll()
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ~(_:) + +
      +
      +
      +
      +
      +
      +

      Computes the complement integer value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public prefix static func ~ (val: APInt) -> APInt
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + val + + +
      +

      The integer value.

      +
      +
      +
      +
      +

      Return Value

      +

      An integer with the value of the bitwise complement.

      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/AddressSpace.html b/docs/Structs/AddressSpace.html new file mode 100644 index 00000000..e3e3286c --- /dev/null +++ b/docs/Structs/AddressSpace.html @@ -0,0 +1,726 @@ + + + + AddressSpace Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    AddressSpace

    +
    +
    + +
    public struct AddressSpace : Equatable
    + +
    +
    +

    An address space is an identifier for a target-specific range of address values. An address space is a +fundamental part of the type of a pointer value and the type of operations that manipulate memory.

    + +

    LLVM affords a default address space (numbered zero) and places a number of assumptions on pointer +values within that address space:

    + +
      +
    • The pointer must have a fixed integral value
    • +
    • The null pointer has a bit-value of 0
    • +
    + +

    These assumptions are not guaranteed to hold in any other address space. In particular, a target may +allow pointers in non-default address spaces to have non-integral types. Non-integral pointer types +represent pointers that have an unspecified bitwise representation; that is, the integral representation may +be target dependent or have an unstable value. Further, outside of the default address space, it is not +always the case that the null pointer value, especially as returned by +IRType.constPointerNull() has a bit value of 0. e.g. A non-default address space may use +an offset-based or segment-based addressing mode in which 0 is a valid, addressable pointer value.

    +

    Target-Level Address Space Overrides

    + +

    A target may choose to override the default address space for code, data, and local allocations through the +data layout string. This has multiple uses. For example, the address space of an alloca is only +configurable via the data layout string, because it is a target-dependent property. There are also +use-cases for overriding language standards e.g. the C standard requires the address-of operator applied +to values on the stack to result in a pointer in the default address space. However, many OpenCL-based +targets consider the stack to be a private region, and place such pointers in a non-default address space.

    + +

    Care must be taken when interacting with these non-standard targets. The IR printer currently does not +print anything when the default address space is attached to an instruction or value, and values will still +report being assigned to that space. However, these values are still subject to the backend’s interpretation +of the data layout string overrides and as such may not always reside in the default address space when +it comes time to codegen them.

    +

    Restrictions

    + +

    There are currently a number of artificial restrictions on values and operations that have non-default +address spaces:

    + +
      +
    • A bitcast between two pointer values residing in different address spaces, even if those two +values have the same size, is always an illegal operation. Use an addrspacecast instead or +always use IRBuilder.buildPointerCast(of:to:name:) to get the correct operation.
    • +
    • The so-called “null pointer” has a bit value that may differ from address space to address space. This +exposes bugs in optimizer passes and lowerings that did not consider this possibility.
    • +
    • A pointer value may not necessarily “round-trip” when converted between address spaces, even if +annotated nonnull and dereferenceable. This is especially true of non-integral pointer types.
    • +
    • Though the zero address space is the default, many backends and some errant passes interpret this to +mean a “lack of address space” and may miscompile code with pointers in mixed address spaces.
    • +
    • A number of intriniscs that operate on memory currently do not support a non-default address space.
    • +
    • The address space is ultimately an integer value and in theory an address space identifier may take on +any value. In practice, LLVM guarantees only 24 bits of precision, though higher address space +identifiers may succeed in being properly represented.
    • +
    + +
    +
    +
    +
      +
    • +
      + + + + zero + +
      +
      +
      +
      +
      +
      +

      LLVM’s default address space.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let zero: AddressSpace
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(_:) + +
      +
      +
      +
      +
      +
      +

      Creates and initializes an address space with the given identifier.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(_ identifier: Int)
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + identifier + + +
      +

      The raw, integral address space identifier.

      +
      +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/Alias.html b/docs/Structs/Alias.html index 30817ba5..35ef8c16 100644 --- a/docs/Structs/Alias.html +++ b/docs/Structs/Alias.html @@ -1,27 +1,35 @@ - Alias Struct Reference + Alias Structure Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    + +
  • +
    + + + + aliasee + +
    +
    +
    +
    +
    +
    +

    The target value of this alias.

    + +

    The aliasee is required to be another global value or constant

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var aliasee: IRValue { get set }
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + previous() + +
    +
    +
    +
    +
    +
    +

    Retrieves the previous alias in the module, if there is one.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func previous() -> Alias?
    + +
    +
    +
    +
    +
  • +
  • +
    + + + + next() + +
    +
    +
    +
    +
    +
    +

    Retrieves the next alias in the module, if there is one.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public func next() -> Alias?
    @@ -378,8 +728,8 @@

    Declaration

    diff --git a/docs/Structs/Alignment.html b/docs/Structs/Alignment.html new file mode 100644 index 00000000..8a1e70ab --- /dev/null +++ b/docs/Structs/Alignment.html @@ -0,0 +1,909 @@ + + + + Alignment Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    Alignment

    +
    +
    + +
    public struct Alignment : Comparable, Hashable
    + +
    +
    +

    An alignment value, expressed in bytes.

    + +
    +
    +
    +
      +
    • +
      + + + + rawValue + +
      +
      +
      +
      +
      +
      +

      Accesses the raw alignment value in bytes.

      +
      +

      Warning

      + This accessor allows breaking out of the Alignment abstraction +for raw alignment calculations. It is therefore not recommended that +this accessor be used in user code. + +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public let rawValue: UInt32
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + zero + +
      +
      +
      +
      +
      +
      +

      A zero-byte alignment value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let zero: Alignment
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + one + +
      +
      +
      +
      +
      +
      +

      An one-byte alignment value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let one: Alignment
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(_:) + +
      +
      +
      +
      +
      +
      +

      Initializes and returns an alignment with the given value interpreted as +a quantity of bytes.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(_ value: UInt32)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + isZero + +
      +
      +
      +
      +
      +
      +

      Returns true if this alignment value is zero bytes, else return false.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var isZero: Bool { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + log2() + +
      +
      +
      +
      +
      +
      +

      Returns the log-base-two value of this alignment as a 32-bit integer.

      + +

      An n-byte alignment contains log-base-two-many least-significant zeros.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func log2() -> UInt32
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + log2() + +
      +
      +
      +
      +
      +
      +

      Returns the log-base-two value of this alignment as a 64-bit integer.

      + +

      An n-byte alignment contains log-base-two-many least-significant zeros.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func log2() -> UInt64
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + alignment(at:) + +
      +
      +
      +
      +
      +
      +

      Returns the alignment of a pointer which points to the given number of +bytes after a pointer with this alignment.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func alignment(at offset: Size) -> Alignment
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ==(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func == (lhs: Alignment, rhs: Alignment) -> Bool
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + <(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func < (lhs: Alignment, rhs: Alignment) -> Bool
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + hash(into:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func hash(into hasher: inout Hasher)
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/ArrayType.html b/docs/Structs/ArrayType.html index 3d67c31d..161ab9de 100644 --- a/docs/Structs/ArrayType.html +++ b/docs/Structs/ArrayType.html @@ -1,27 +1,35 @@ - ArrayType Struct Reference + ArrayType Structure Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
  • +
  • +
    + + + + name + +
    +
    +
    +
    +
    +
    +

    Retrieves the name of this basic block.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var name: String { get }
    @@ -414,9 +860,9 @@

    Declaration

  • @@ -431,7 +877,7 @@

    Declaration

    Declaration

    Swift

    -
    public var firstInstruction: Instruction?
    +
    public var firstInstruction: IRInstruction? { get }
    @@ -441,9 +887,9 @@

    Declaration

  • @@ -458,7 +904,7 @@

    Declaration

    Declaration

    Swift

    -
    public var lastInstruction: Instruction?
    +
    public var lastInstruction: IRInstruction? { get }
    @@ -468,9 +914,9 @@

    Declaration

  • @@ -486,7 +932,7 @@

    Declaration

    Declaration

    Swift

    -
    public var terminator: TerminatorInstruction?
    +
    public var terminator: TerminatorInstruction? { get }
    @@ -496,9 +942,9 @@

    Declaration

  • - + - parent + parent
    @@ -513,7 +959,7 @@

    Declaration

    Declaration

    Swift

    -
    public var parent: Function?
    +
    public var parent: Function? { get }
    @@ -523,9 +969,9 @@

    Declaration

  • - + - next() + next()
    @@ -540,7 +986,7 @@

    Declaration

    Declaration

    Swift

    -
    public func next() -> BasicBlock?
    +
    public func next() -> BasicBlock?
    @@ -550,9 +996,9 @@

    Declaration

  • @@ -567,7 +1013,7 @@

    Declaration

    Declaration

    Swift

    -
    public func previous() -> BasicBlock?
    +
    public func previous() -> BasicBlock?
    @@ -577,9 +1023,9 @@

    Declaration

  • @@ -594,7 +1040,7 @@

    Declaration

    Declaration

    Swift

    -
    public var instructions: AnySequence<Instruction>
    +
    public var instructions: AnySequence<IRInstruction> { get }
    @@ -604,9 +1050,9 @@

    Declaration

  • @@ -628,7 +1074,7 @@

    Declaration

    Declaration

    Swift

    -
    public func removeFromParent()
    +
    public func removeFromParent()
    @@ -638,9 +1084,9 @@

    Declaration

  • @@ -655,7 +1101,7 @@

    Declaration

    Declaration

    Swift

    -
    public func moveBefore(_ block: BasicBlock)
    +
    public func moveBefore(_ block: BasicBlock)
    @@ -665,9 +1111,9 @@

    Declaration

  • @@ -682,23 +1128,19 @@

    Declaration

    Declaration

    Swift

    -
    public func moveAfter(_ block: BasicBlock)
    +
    public func moveAfter(_ block: BasicBlock)
  • - - -
    -
    • - - - delete() + + + Address
      @@ -706,37 +1148,28 @@

      Declaration

      -

      Deletes the basic block from its containing function.

      -
      -

      Note

      - This does not remove breaks to this block from the - function. Ensure you have removed all instructions that reference - this basic block before deleting it. - -
      +

      An Address represents a function-relative address of a basic block for +use with the indirectbr instruction.

      + See more

      Declaration

      Swift

      -
      public func delete()
      +
      public struct Address : IRValue
    • -
    -
    -
    -
    diff --git a/docs/Structs/Call.html b/docs/Structs/Call.html index 80bf7986..dd656951 100644 --- a/docs/Structs/Call.html +++ b/docs/Structs/Call.html @@ -1,27 +1,35 @@ - Call Struct Reference + Call Structure Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    diff --git a/docs/Structs/Call/TailCallKind.html b/docs/Structs/Call/TailCallKind.html new file mode 100644 index 00000000..2566afc8 --- /dev/null +++ b/docs/Structs/Call/TailCallKind.html @@ -0,0 +1,788 @@ + + + + TailCallKind Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    TailCallKind

    +
    +
    + +
    public enum TailCallKind
    + +
    +
    +

    Optimization markers for tail call elimination.

    + +
    +
    +
    +
      +
    • +
      + + + + none + +
      +
      +
      +
      +
      +
      +

      No optimization tail call marker is present. The optimizer is free to +infer one of the other tail call markers.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case none
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + tail + +
      +
      +
      +
      +
      +
      +

      Suggests that tail call optimization should be performed on this +function. Note that this is not a guarantee.

      + +

      tail calls may not access caller-provided allocas, and may not +access varargs.

      + +

      Tail call optimization for calls marked tail is guaranteed to occur if +the following conditions are met:

      + +
        +
      • Caller and callee both have the calling convention fastcc.
      • +
      • The call is in tail position (ret immediately follows call and +ret uses value of call or is void).
      • +
      • Tail call elimination is enabled in the target machine’s +TargetOptions or is globally enabled in LLVM.
      • +
      • Platform-specific constraints are met.
      • +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case tail
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + mustTail + +
      +
      +
      +
      +
      +
      +

      Requires the tail call optimization be performed in order for this call +to proceed correctly.

      + +

      Tail calls guarantee the following invariants:

      + +
        +
      • The call will not cause unbounded stack growth if it is part of a +recursive cycle in the call graph.
      • +
      • Arguments with the inalloca attribute are forwarded in place.
      • +
      • If the musttail call appears in a function with the thunk +attribute and the caller and callee both have varargs, than any +unprototyped arguments in register or memory are forwarded to the +callee. Similarly, the return value of the callee is returned the +the caller’s caller, even if a void return type is in use.
      • +
      + +

      mustTail calls may not access caller-provided allocas, and may not +access varargs. Unlike tails, they are also subject to the following +restrictions:

      + +
        +
      • The call must immediately precede a ret instruction, or a pointer +bitcast followed by a ret instruction.
      • +
      • The ret instruction must return the (possibly bitcasted) value +produced by the call, or return void.
      • +
      • The caller and callee prototypes must match. Pointer types of +parameters or return types may differ in pointee type, but not in +address space.
      • +
      • The calling conventions of the caller and callee must match.
      • +
      • All ABI-impacting function attributes, such as sret, byval, +inreg, returned, and inalloca, must match.
      • +
      • The callee must be varargs iff the caller is varargs. Bitcasting a +non-varargs function to the appropriate varargs type is legal so +long as the non-varargs prefixes obey the other rules.
      • +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case mustTail
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + noTail + +
      +
      +
      +
      +
      +
      +

      Prevents tail call optimizations from being performed or inferred.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case noTail
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + llvm + +
      +
      +
      +
      +
      +
      +

      Retrieves the corresponding LLVMTailCallKind.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var llvm: LLVMTailCallKind { get }
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/CompileUnitMetadata.html b/docs/Structs/CompileUnitMetadata.html new file mode 100644 index 00000000..47d16085 --- /dev/null +++ b/docs/Structs/CompileUnitMetadata.html @@ -0,0 +1,663 @@ + + + + CompileUnitMetadata Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    CompileUnitMetadata

    +
    +
    + +
    public struct CompileUnitMetadata : DIScope
    + +
    +
    +

    CompileUnitMetadata nodes represent a compile unit, the root of a metadata +hierarchy for a translation unit.

    + +

    Compile unit descriptors provide the root scope for objects declared in a +specific compilation unit. FileMetadata descriptors are defined using this +scope.

    + +

    These descriptors are collected by a named metadata node !llvm.dbg.cu. +They keep track of global variables, type information, and imported entities +(declarations and namespaces).

    + +
    +
    +
    +
      +
    • +
      + + + + asMetadata() + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func asMetadata() -> LLVMMetadataRef
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(llvm:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(llvm: LLVMMetadataRef)
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/Constant.html b/docs/Structs/Constant.html index a36d3d33..697244ea 100644 --- a/docs/Structs/Constant.html +++ b/docs/Structs/Constant.html @@ -1,27 +1,35 @@ - Constant Struct Reference + Constant Structure Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@
    - - - -

    Casting

    -
    + + +
    + +

    Negation

    +

    +
    • @@ -404,14 +648,14 @@

      Casting

      -

      Creates a constant cast to a given integral type.

      +

      Creates a constant negate operation to negate a value.

      Declaration

      Swift

      -
      public func cast<T: IntegralConstantRepresentation>(to type: IntType) -> Constant<T>
      +
      public static func negate(_ lhs: Constant<Signed>, overflowBehavior: OverflowBehavior = .default) -> Constant<Signed>
      @@ -422,12 +666,25 @@

      Parameters

      - type + lhs
      -

      The type to cast towards.

      +

      The operand to negate.

      +
      + + + + + + overflowBehavior + + + +
      +

      Should overflow occur, specifies the +behavior of the resulting constant value.

      @@ -436,8 +693,7 @@

      Parameters

      Return Value

      -

      A const value representing this value cast to the given -integral type.

      +

      A constant value representing the negation of the given constant.

    @@ -445,9 +701,9 @@

    Return Value

  • - - - cast(to:) + + + negate(_:)
    @@ -455,14 +711,14 @@

    Return Value

    -

    Creates a constant cast to a given floating type.

    +

    Creates a constant negate operation to negate a value.

    Declaration

    Swift

    -
    public func cast(to type: FloatType) -> Constant<Floating>
    +
    public static func negate(_ lhs: Constant<Floating>) -> Constant<Floating>
    @@ -473,12 +729,12 @@

    Parameters

    - type + lhs
    -

    The type to cast towards.

    +

    The operand to negate.

    @@ -487,8 +743,7 @@

    Parameters

    Return Value

    -

    A const value representing this value cast to the given -floating type.

    +

    A constant value representing the negation of the given constant.

    @@ -497,19 +752,21 @@

    Return Value

    - - - -

    Arithmetic Operations

    -
    + + +
    + +

    Addition

    +

    +
    • @@ -517,14 +774,14 @@

      Arithmetic Operations

      -

      Creates a constant negate operation to negate a value.

      +

      Creates a constant add operation to add two homogenous constants together.

      Declaration

      Swift

      -
      public static func negate(_ lhs: Constant<Signed>, overflowBehavior: OverflowBehavior = .default) -> Constant<Signed>
      +
      public static func add(_ lhs: Constant<Unsigned>, _ rhs: Constant<Unsigned>, overflowBehavior: OverflowBehavior = .default) -> Constant<Unsigned>
      @@ -540,7 +797,19 @@

      Parameters

      -

      The operand to negate.

      +

      The first summand value (the augend).

      +
      + + + + + + rhs + + + +
      +

      The second summand value (the addend).

      @@ -562,7 +831,7 @@

      Parameters

      Return Value

      -

      A constant value representing the negation of the given constant.

      +

      A constant value representing the sum of the two operands.

    @@ -570,9 +839,9 @@

    Return Value

  • @@ -587,7 +856,7 @@

    Return Value

    Declaration

    Swift

    -
    public static func add(_ lhs: Constant, _ rhs: Constant, overflowBehavior: OverflowBehavior = .default) -> Constant
    +
    public static func add(_ lhs: Constant<Signed>, _ rhs: Constant<Signed>, overflowBehavior: OverflowBehavior = .default) -> Constant<Signed>
    @@ -645,9 +914,9 @@

    Return Value

  • - - - +(_:_:) + + + add(_:_:)
    @@ -655,14 +924,14 @@

    Return Value

    -

    A constant add operation to add two homogenous constants together.

    +

    Creates a constant add operation to add two homogenous constants together.

    Declaration

    Swift

    -
    public static func +(lhs: Constant, rhs: Constant) -> Constant
    +
    public static func add(_ lhs: Constant<Floating>, _ rhs: Constant<Floating>) -> Constant<Floating>
    @@ -704,12 +973,25 @@

    Return Value

  • + + +
    +
    + + +
    + +

    Subtraction

    +

    +
    +
    +
    + + + + overflowBehavior + + + +
    +

    Should overflow occur, specifies the +behavior of the resulting constant value.

    +
    + + @@ -844,9 +1139,9 @@

    Return Value

  • @@ -854,14 +1149,6008 @@

    Return Value

    -

    Creates a constant multiply operation with the given values as operands.

    +

    Creates a constant sub operation to subtract two homogenous constants.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public static func subtract(_ lhs: Constant<Floating>, _ rhs: Constant<Floating>) -> Constant<Floating>
    + +
    +
    +
    +

    Parameters

    + + + + + + + + + + + +
    + + lhs + + +
    +

    The first value (the minuend).

    +
    +
    + + rhs + + +
    +

    The second value (the subtrahend).

    +
    +
    +
    +
    +

    Return Value

    +

    A constant value representing the difference of the two operands.

    +
    +
    +
    +
  • + + +
    +
    + + +
    + +

    Multiplication

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Creates a constant multiply operation with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func multiply(_ lhs: Constant<Unsigned>, _ rhs: Constant<Unsigned>, overflowBehavior: OverflowBehavior = .default) -> Constant<Unsigned>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + lhs + + +
      +

      The first factor value (the multiplier).

      +
      +
      + + rhs + + +
      +

      The second factor value (the multiplicand).

      +
      +
      + + overflowBehavior + + +
      +

      Should overflow occur, specifies the +behavior of the resulting constant value.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the product of the two operands.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Creates a constant multiply operation with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func multiply(_ lhs: Constant<Signed>, _ rhs: Constant<Signed>, overflowBehavior: OverflowBehavior = .default) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + lhs + + +
      +

      The first factor value (the multiplier).

      +
      +
      + + rhs + + +
      +

      The second factor value (the multiplicand).

      +
      +
      + + overflowBehavior + + +
      +

      Should overflow occur, specifies the +behavior of the resulting constant value.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the product of the two operands.

      +
      +
      +
      +
    • +
    • +
      + + + + multiply(_:_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant multiply operation with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func multiply(_ lhs: Constant<Floating>, _ rhs: Constant<Floating>) -> Constant<Floating>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first factor value (the multiplier).

      +
      +
      + + rhs + + +
      +

      The second factor value (the multiplicand).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the product of the two operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Divide

    +

    +
    +
    +
      +
    • +
      + + + + divide(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant divide operation that provides the remainder after divison of +the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func divide(_ lhs: Constant<Unsigned>, _ rhs: Constant<Unsigned>) -> Constant<Unsigned>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the dividend).

      +
      +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the quotient of the first and +second operands.

      +
      +
      +
      +
    • +
    • +
      + + + + divide(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant divide operation that provides the remainder after divison of +the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func divide(_ lhs: Constant<Signed>, _ rhs: Constant<Signed>) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the dividend).

      +
      +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the quotient of the first and +second operands.

      +
      +
      +
      +
    • +
    • +
      + + + + divide(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant divide operation that provides the remainder after divison of +the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func divide(_ lhs: Constant<Floating>, _ rhs: Constant<Floating>) -> Constant<Floating>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the dividend).

      +
      +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the quotient of the first and +second operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Remainder

    +

    +
    +
    +
      +
    • +
      + + + + remainder(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant remainder operation that provides the remainder after divison +of the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func remainder(_ lhs: Constant<Unsigned>, _ rhs: Constant<Unsigned>) -> Constant<Unsigned>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the dividend).

      +
      +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the remainder of division of the +first operand by the second operand.

      +
      +
      +
      +
    • +
    • +
      + + + + remainder(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant remainder operation that provides the remainder after divison +of the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func remainder(_ lhs: Constant<Signed>, _ rhs: Constant<Signed>) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the dividend).

      +
      +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the remainder of division of the +first operand by the second operand.

      +
      +
      +
      +
    • +
    • +
      + + + + remainder(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant remainder operation that provides the remainder after divison +of the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func remainder(_ lhs: Constant<Floating>, _ rhs: Constant<Floating>) -> Constant<Floating>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the dividend).

      +
      +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the remainder of division of the +first operand by the second operand.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Logical Operations

    +

    +
    +
    +
      +
    • +
      + + + + not(_:) + +
      +
      +
      +
      +
      +
      +

      A constant bitwise logical not with the given integral value as an operand.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func not<T>(_ lhs: Constant<T>) -> Constant<T> where T : IntegralConstantRepresentation
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + val + + +
      +

      The value to negate.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the logical negation of the given +operand.

      +
      +
      +
      +
    • +
    • +
      + + + + and(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant bitwise logical AND with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func and<T>(_ lhs: Constant<T>, _ rhs: Constant<T>) -> Constant<T> where T : IntegralConstantRepresentation
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + lhs + + +
      +

      The first operand.

      +
      +
      + + rhs + + +
      +

      The second operand.

      +
      +
      + + name + + +
      +

      The name for the newly inserted instruction.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the logical OR of the values of +the two given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + or(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant bitwise logical OR with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func or<T>(_ lhs: Constant<T>, _ rhs: Constant<T>) -> Constant<T> where T : IntegralConstantRepresentation
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + lhs + + +
      +

      The first operand.

      +
      +
      + + rhs + + +
      +

      The second operand.

      +
      +
      + + name + + +
      +

      The name for the newly inserted instruction.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the logical OR of the values of +the two given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + xor(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant bitwise logical exclusive OR with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func xor<T>(_ lhs: Constant<T>, _ rhs: Constant<T>) -> Constant<T> where T : IntegralConstantRepresentation
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first operand.

      +
      +
      + + rhs + + +
      +

      The second operand.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the exclusive OR of the values of +the two given operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Bitshifting Operations

    +

    +
    +
    +
      +
    • +
      + + + + leftShift(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant left-shift of the first value by the second amount.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func leftShift<T>(_ lhs: Constant<T>, _ rhs: Constant<T>) -> Constant<T> where T : IntegralConstantRepresentation
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first operand.

      +
      +
      + + rhs + + +
      +

      The second operand.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the value of the first operand +shifted left by the number of bits specified in the second operand.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      A constant right-shift of the first value by the second amount.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func rightShift<T>(_ lhs: Constant<T>, _ rhs: Constant<T>, arithmetic: Bool = true) -> Constant<T> where T : IntegralConstantRepresentation
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + lhs + + +
      +

      The first operand.

      +
      +
      + + rhs + + +
      +

      The second operand.

      +
      +
      + + arithmetic + + +
      +

      Should the shift be arithmetic or logical (defaults to true)

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the value of the first operand +shifted left by the number of bits specified in the second operand.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Conditional Operations

    +

    +
    +
    +
      +
    • +
      + + + + select(_:then:else:) + +
      +
      +
      +
      +
      +
      +

      A constant select using the given condition to select among two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func select<T, U>(_ cond: Constant<T>, then: Constant<U>, else: Constant<U>) -> Constant<U> where T : IntegralConstantRepresentation, U : ConstantRepresentation
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + cond + + +
      +

      The condition to evaluate. It must have type i1 or +be a vector of i1.

      +
      +
      + + then + + +
      +

      The value to select if the given condition is true.

      +
      +
      + + else + + +
      +

      The value to select if the given condition is false.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the constant value selected for +by the condition.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr: IntegralConstantRepresentation

    +

    +
    +
    +
      +
    • +
      + + + + cast(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant cast to a given integral type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func cast(to type: IntType) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to cast towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value cast to the given +integral type.

      +
      +
      +
      +
    • +
    • +
      + + + + cast(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant cast to a given integral type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func cast(to type: IntType) -> Constant<Unsigned>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to cast towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value cast to the given +integral type.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Unsigned

    +

    +
    +
    +
      +
    • +
      + + + + cast(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant cast to a given floating type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func cast(to type: FloatType) -> Constant<Floating>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to cast towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value cast to the given +floating type.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Signed

    +

    +
    +
    +
      +
    • +
      + + + + cast(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant cast to a given integral type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func cast(to type: IntType) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to cast towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value cast to the given +integral type.

      +
      +
      +
      +
    • +
    • +
      + + + + cast(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant cast to a given integral type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func cast(to type: IntType) -> Constant<Unsigned>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to cast towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value cast to the given +integral type.

      +
      +
      +
      +
    • +
    • +
      + + + + cast(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant cast to a given floating type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func cast(to type: FloatType) -> Constant<Floating>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to cast towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value cast to the given +floating type.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Floating

    +

    +
    +
    +
      +
    • +
      + + + + cast(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant cast to a given integral type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func cast(to type: IntType) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to cast towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value cast to the given +integral type.

      +
      +
      +
      +
    • +
    • +
      + + + + cast(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant cast to a given integral type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func cast(to type: IntType) -> Constant<Unsigned>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to cast towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value cast to the given +integral type.

      +
      +
      +
      +
    • +
    • +
      + + + + cast(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant cast to a given floating type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func cast(to type: FloatType) -> Constant<Floating>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to cast towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value cast to the given +floating type.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Signed

    +

    +
    +
    +
      +
    • +
      + + + + truncate(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant truncated to a given integral type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func truncate(to type: IntType) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to truncate towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value truncated to the given +integral type’s bitwidth.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Unsigned

    +

    +
    +
    +
      +
    • +
      + + + + truncate(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant truncated to a given integral type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func truncate(to type: IntType) -> Constant<Unsigned>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to truncate towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value truncated to the given +integral type’s bitwidth.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Floating

    +

    +
    +
    +
      +
    • +
      + + + + truncate(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant truncated to a given floating type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func truncate(to type: FloatType) -> Constant<Floating>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to truncate towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value truncated to the given +floating type’s bitwidth.

      +
      +
      +
      +
    • +
    • +
      + + + + extend(to:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant extended to a given floating type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func extend(to type: FloatType) -> Constant<Floating>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + type + + +
      +

      The type to extend towards.

      +
      +
      +
      +
      +

      Return Value

      +

      A const value representing this value extended to the given +floating type’s bitwidth.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Signed

    +

    +
    +
    +
      +
    • +
      + + + + negate() + +
      +
      +
      +
      +
      +
      +

      Creates a constant negate operation to negate a value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func negate() -> Constant
      + +
      +
      +
      +

      Return Value

      +

      A constant value representing the negation of the given constant.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Floating

    +

    +
    +
    +
      +
    • +
      + + + + negate() + +
      +
      +
      +
      +
      +
      +

      Creates a constant negate operation to negate a value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func negate() -> Constant
      + +
      +
      +
      +

      Return Value

      +

      A constant value representing the negation of the given constant.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Signed

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Creates a constant add operation to add two homogenous constants together.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func adding(_ rhs: Constant, overflowBehavior: OverflowBehavior = .default) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + rhs + + +
      +

      The second summand value (the addend).

      +
      +
      + + overflowBehavior + + +
      +

      Should overflow occur, specifies the +behavior of the resulting constant value.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the sum of the two operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Unsigned

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Creates a constant add operation to add two homogenous constants together.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func adding(_ rhs: Constant, overflowBehavior: OverflowBehavior = .default) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + rhs + + +
      +

      The second summand value (the addend).

      +
      +
      + + overflowBehavior + + +
      +

      Should overflow occur, specifies the +behavior of the resulting constant value.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the sum of the two operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Floating

    +

    +
    +
    +
      +
    • +
      + + + + adding(_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant add operation to add two homogenous constants together.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func adding(_ rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + rhs + + +
      +

      The second summand value (the addend).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the sum of the two operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Unsigned

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Creates a constant sub operation to subtract two homogenous constants.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func subtracting(_ rhs: Constant, overflowBehavior: OverflowBehavior = .default) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + rhs + + +
      +

      The second value (the subtrahend).

      +
      +
      + + overflowBehavior + + +
      +

      Should overflow occur, specifies the +behavior of the resulting constant value.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the difference of the two operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Signed

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Creates a constant sub operation to subtract two homogenous constants.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func subtracting(_ rhs: Constant, overflowBehavior: OverflowBehavior = .default) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + rhs + + +
      +

      The second value (the subtrahend).

      +
      +
      + + overflowBehavior + + +
      +

      Should overflow occur, specifies the +behavior of the resulting constant value.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the difference of the two operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Floating

    +

    +
    +
    +
      +
    • +
      + + + + subtracting(_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant sub operation to subtract two homogenous constants.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func subtracting(_ rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + rhs + + +
      +

      The second value (the subtrahend).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the difference of the two operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Unsigned

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Creates a constant multiply operation with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func multiplying(_ rhs: Constant, overflowBehavior: OverflowBehavior = .default) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + rhs + + +
      +

      The second factor value (the multiplicand).

      +
      +
      + + overflowBehavior + + +
      +

      Should overflow occur, specifies the +behavior of the resulting constant value.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the product of the two operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Signed

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Creates a constant multiply operation with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func multiplying(_ rhs: Constant, overflowBehavior: OverflowBehavior = .default) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + rhs + + +
      +

      The second factor value (the multiplicand).

      +
      +
      + + overflowBehavior + + +
      +

      Should overflow occur, specifies the +behavior of the resulting constant value.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the product of the two operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Floating

    +

    +
    +
    +
      +
    • +
      + + + + multiplying(_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant multiply operation with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func multiplying(_ rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first factor value (the multiplier).

      +
      +
      + + rhs + + +
      +

      The second factor value (the multiplicand).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the product of the two operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Unsigned

    +

    +
    +
    +
      +
    • +
      + + + + dividing(by:) + +
      +
      +
      +
      +
      +
      +

      A constant divide operation that provides the remainder after divison of +the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func dividing(by rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the quotient of the first and +second operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Signed

    +

    +
    +
    +
      +
    • +
      + + + + dividing(by:) + +
      +
      +
      +
      +
      +
      +

      A constant divide operation that provides the remainder after divison of +the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func dividing(by rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the quotient of the first and +second operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Floating

    +

    +
    +
    +
      +
    • +
      + + + + dividing(by:) + +
      +
      +
      +
      +
      +
      +

      A constant divide operation that provides the remainder after divison of +the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func dividing(by rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the quotient of the first and +second operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Unsigned

    +

    +
    +
    +
      +
    • +
      + + + + remainder(_:) + +
      +
      +
      +
      +
      +
      +

      A constant remainder operation that provides the remainder after divison +of the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func remainder(_ rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the remainder of division of the +first operand by the second operand.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Signed

    +

    +
    +
    +
      +
    • +
      + + + + remainder(_:) + +
      +
      +
      +
      +
      +
      +

      A constant remainder operation that provides the remainder after divison +of the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func remainder(_ rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the remainder of division of the +first operand by the second operand.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Floating

    +

    +
    +
    +
      +
    • +
      + + + + remainder(_:) + +
      +
      +
      +
      +
      +
      +

      A constant remainder operation that provides the remainder after divison +of the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func remainder(_ rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the remainder of division of the +first operand by the second operand.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr: IntegralConstantRepresentation

    +

    +
    +
    +
      +
    • +
      + + + + equals(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant equality comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func equals(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Signed

    +

    +
    +
    +
      +
    • +
      + + + + lessThan(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant less-than comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func lessThan(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + greaterThan(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant greater-than comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func greaterThan(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + lessThanOrEqual(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant less-than-or-equal comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func lessThanOrEqual(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      A constant greater-than-or-equal comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func greaterThanOrEqual(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Unsigned

    +

    +
    +
    +
      +
    • +
      + + + + lessThan(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant less-than comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func lessThan(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + greaterThan(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant greater-than comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func greaterThan(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + lessThanOrEqual(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant less-than-or-equal comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func lessThanOrEqual(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      A constant greater-than-or-equal comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func greaterThanOrEqual(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Floating

    +

    +
    +
    +
      +
    • +
      + + + + equals(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant equality comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func equals(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + lessThan(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant less-than comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func lessThan(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + greaterThan(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant greater-than comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func greaterThan(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + lessThanOrEqual(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant less-than-or-equal comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func lessThanOrEqual(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      A constant greater-than-or-equal comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func greaterThanOrEqual(_ lhs: Constant, _ rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr: IntegralConstantRepresentation

    +

    +
    +
    +
      +
    • +
      + + + + pointerToInt(_:_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant pointer-to-integer operation to convert the given constant +global pointer value to the given integer type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func pointerToInt(_ val: IRConstant, _ intType: IntType) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + val + + +
      +

      The pointer value.

      +
      +
      + + intType + + +
      +

      The destination integer type.

      +
      +
      +
      +
      +

      Return Value

      +

      An constant value representing the constant value of the given +pointer converted to the given integer type.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Struct

    +

    +
    +
    +
      +
    • +
      + + + + getElement(indices:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant operation retrieving the element at the index.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func getElement(indices: [Int]) -> IRConstant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + indices + + +
      +

      A list of indices that indicate which of the elements +of the aggregate object are indexed.

      +
      +
      +
      +
      +

      Return Value

      +

      The value in the struct at the provided index.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Build a constant GEP (Get Element Pointer) instruction with a resultant +value that is undefined if the address is outside the actual underlying +allocated object and not the address one-past-the-end.

      + +

      The GEP instruction is often the source of confusion. LLVM provides a +document to answer questions +around its semantics and correct usage.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func getElementPointer(indices: [IRConstant]) -> IRConstant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + indices + + +
      +

      A list of indices that indicate which of the elements +of the aggregate object are indexed.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing the address of a subelement of the given +aggregate data structure value.

      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Build a GEP (Get Element Pointer) instruction.

      + +

      The GEP instruction is often the source of confusion. LLVM provides a +document to answer questions +around its semantics and correct usage.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func inBoundsGetElementPointer(indices: [IRConstant]) -> IRConstant
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + indices + + +
      +

      A list of indices that indicate which of the elements +of the aggregate object are indexed.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing the address of a subelement of the given +aggregate data structure value.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Vector

    +

    +
    +
    +
      +
    • + +
      +
      +
      +
      +
      +

      Builds a constant operation to construct a permutation of elements +from the two given input vectors, returning a vector with the same element +type as the inputs and length that is the same as the shuffle mask.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func buildShuffleVector(_ vector1: Constant, and vector2: Constant, mask: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + + + + + +
      + + vector1 + + +
      +

      The first constant vector to shuffle.

      +
      +
      + + vector2 + + +
      +

      The second constant vector to shuffle.

      +
      +
      + + mask + + +
      +

      A constant vector of i32 values that acts as a mask +for the shuffled vectors.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing a constant vector with the same element +type as the inputs and length that is the same as the shuffle mask.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Floating

    +

    +
    +
    +
      +
    • +
      + + + + +(_:_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant add operation to add two homogenous constants together.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func + (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first summand value (the augend).

      +
      +
      + + rhs + + +
      +

      The second summand value (the addend).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the sum of the two operands.

      +
      +
      +
      +
    • +
    • +
      + + + + -(_:_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant sub operation to subtract two homogenous constants.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func - (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the minuend).

      +
      +
      + + rhs + + +
      +

      The second value (the subtrahend).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the difference of the two operands.

      +
      +
      +
      +
    • +
    • +
      + + + + *(_:_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant multiply operation with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func * (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first factor value (the multiplier).

      +
      +
      + + rhs + + +
      +

      The second factor value (the multiplicand).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the product of the two operands.

      +
      +
      +
      +
    • +
    • +
      + + + + /(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant divide operation that provides the remainder after divison of +the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func / (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the dividend).

      +
      +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the quotient of the first and +second operands.

      +
      +
      +
      +
    • +
    • +
      + + + + %(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant remainder operation that provides the remainder after divison +of the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func % (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the dividend).

      +
      +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the remainder of division of the +first operand by the second operand.

      +
      +
      +
      +
    • +
    • +
      + + + + ==(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant equality comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func == (lhs: Constant, rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + <(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant less-than comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func < (lhs: Constant, rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + >(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant greater-than comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func > (lhs: Constant, rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + <=(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant less-than-or-equal comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func <= (lhs: Constant, rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + >=(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant greater-than-or-equal comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func >= (lhs: Constant, rhs: Constant) -> Constant<Signed>
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Signed

    +

    +
    +
    +
      +
    • +
      + + + + +(_:_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant add operation to add two homogenous constants together.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func + (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first summand value (the augend).

      +
      +
      + + rhs + + +
      +

      The second summand value (the addend).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the sum of the two operands.

      +
      +
      +
      +
    • +
    • +
      + + + + -(_:_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant sub operation to subtract two homogenous constants.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func - (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the minuend).

      +
      +
      + + rhs + + +
      +

      The second value (the subtrahend).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the difference of the two operands.

      +
      +
      +
      +
    • +
    • +
      + + + + *(_:_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant multiply operation with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func * (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first factor value (the multiplier).

      +
      +
      + + rhs + + +
      +

      The second factor value (the multiplicand).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the product of the two operands.

      +
      +
      +
      +
    • +
    • +
      + + + + /(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant divide operation that provides the remainder after divison of +the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func / (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the dividend).

      +
      +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the quotient of the first and +second operands.

      +
      +
      +
      +
    • +
    • +
      + + + + %(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant remainder operation that provides the remainder after divison +of the first value by the second value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func % (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value (the dividend).

      +
      +
      + + rhs + + +
      +

      The second value (the divisor).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the remainder of division of the +first operand by the second operand.

      +
      +
      +
      +
    • +
    • +
      + + + + ==(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant equality comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func == (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + <(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant less-than comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func < (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + >(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant greater-than comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func > (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + <=(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant less-than-or-equal comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func <= (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + >=(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant greater-than-or-equal comparison between two values.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func >= (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first value to compare.

      +
      +
      + + rhs + + +
      +

      The second value to compare.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant integral value (i1) representing the result of the +comparision of the given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + |(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant bitwise logical OR with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func | (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first operand.

      +
      +
      + + rhs + + +
      +

      The second operand.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the logical OR of the values of +the two given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + &(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant bitwise logical AND with the given values as operands.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func & (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first operand.

      +
      +
      + + rhs + + +
      +

      The second operand.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the logical OR of the values of +the two given operands.

      +
      +
      +
      +
    • +
    • +
      + + + + <<(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant left-shift of the first value by the second amount.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func << (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first operand.

      +
      +
      + + rhs + + +
      +

      The second operand.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the value of the first operand +shifted left by the number of bits specified in the second operand.

      +
      +
      +
      +
    • +
    • +
      + + + + >>(_:_:) + +
      +
      +
      +
      +
      +
      +

      A constant right-shift of the first value by the second amount.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func >> (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first operand.

      +
      +
      + + rhs + + +
      +

      The second operand.

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the value of the first operand +shifted left by the number of bits specified in the second operand.

      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Unsigned

    +

    +
    +
    +
      +
    • +
      + + + + +(_:_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant add operation to add two homogenous constants together.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func + (lhs: Constant, rhs: Constant) -> Constant
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + lhs + + +
      +

      The first summand value (the augend).

      +
      +
      + + rhs + + +
      +

      The second summand value (the addend).

      +
      +
      +
      +
      +

      Return Value

      +

      A constant value representing the sum of the two operands.

      +
      +
      +
      +
    • +
    • +
      + + + + -(_:_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant sub operation to subtract two homogenous constants.

      Declaration

      Swift

      -
      public static func multiply(_ lhs: Constant, _ rhs: Constant, overflowBehavior: OverflowBehavior = .default) -> Constant
      +
      public static func - (lhs: Constant, rhs: Constant) -> Constant
      @@ -877,7 +7166,7 @@

      Parameters

      -

      The first factor value (the multiplier).

      +

      The first value (the minuend).

      @@ -889,20 +7178,7 @@

      Parameters

      -

      The second factor value (the multiplicand).

      -
      - - - - - - overflowBehavior - - - -
      -

      Should overflow occur, specifies the -behavior of the resulting constant value.

      +

      The second value (the subtrahend).

      @@ -911,7 +7187,7 @@

      Parameters

      Return Value

      -

      A constant value representing the product of the two operands.

      +

      A constant value representing the difference of the two operands.

    @@ -919,9 +7195,9 @@

    Return Value

  • - + - *(_:_:) + *(_:_:)
    @@ -929,14 +7205,14 @@

    Return Value

    -

    A constant multiply operation with the given values as operands.

    +

    Creates a constant multiply operation with the given values as operands.

    Declaration

    Swift

    -
    public static func *(lhs: Constant, rhs: Constant) -> Constant
    +
    public static func * (lhs: Constant, rhs: Constant) -> Constant
    @@ -981,9 +7257,9 @@

    Return Value

  • - + - /(_:_:) + /(_:_:)
    @@ -999,7 +7275,7 @@

    Return Value

    Declaration

    Swift

    -
    public static func /(lhs: Constant, rhs: Constant) -> Constant
    +
    public static func / (lhs: Constant, rhs: Constant) -> Constant
    @@ -1036,7 +7312,7 @@

    Parameters

  • Return Value

    -

    A constant value representing the quotient of the first and +

    A constant value representing the quotient of the first and second operands.

    @@ -1045,9 +7321,9 @@

    Return Value

  • - + - %(_:_:) + %(_:_:)
    @@ -1055,7 +7331,7 @@

    Return Value

    -

    A constant remainder operation that provides the remainder after divison +

    A constant remainder operation that provides the remainder after divison of the first value by the second value.

    @@ -1063,7 +7339,7 @@

    Return Value

    Declaration

    Swift

    -
    public static func %(lhs: Constant, rhs: Constant) -> Constant
    +
    public static func % (lhs: Constant, rhs: Constant) -> Constant
    @@ -1106,23 +7382,12 @@

    Return Value

  • - - -
    - -
    • - + - ==(_:_:) + ==(_:_:)
      @@ -1137,7 +7402,7 @@

      Comparison Operations

      Declaration

      Swift

      -
      public static func ==(lhs: Constant, rhs: Constant) -> Constant<Signed>
      +
      public static func == (lhs: Constant, rhs: Constant) -> Constant<Signed>
      @@ -1174,7 +7439,7 @@

      Parameters

    Return Value

    -

    A constant integral value (i1) representing the result of the +

    A constant integral value (i1) representing the result of the comparision of the given operands.

    @@ -1183,9 +7448,9 @@

    Return Value

  • - + - <(_:_:) + <(_:_:)
    @@ -1200,7 +7465,7 @@

    Return Value

    Declaration

    Swift

    -
    public static func <(lhs: Constant, rhs: Constant) -> Constant<Signed>
    +
    public static func < (lhs: Constant, rhs: Constant) -> Constant<Signed>
    @@ -1246,9 +7511,9 @@

    Return Value

  • - + - >(_:_:) + >(_:_:)
    @@ -1263,7 +7528,7 @@

    Return Value

    Declaration

    Swift

    -
    public static func >(lhs: Constant, rhs: Constant) -> Constant<Signed>
    +
    public static func > (lhs: Constant, rhs: Constant) -> Constant<Signed>
    @@ -1309,9 +7574,9 @@

    Return Value

  • - + - <=(_:_:) + <=(_:_:)
    @@ -1326,7 +7591,7 @@

    Return Value

    Declaration

    Swift

    -
    public static func <=(lhs: Constant, rhs: Constant) -> Constant<Signed>
    +
    public static func <= (lhs: Constant, rhs: Constant) -> Constant<Signed>
    @@ -1372,9 +7637,9 @@

    Return Value

  • - + - >=(_:_:) + >=(_:_:)
    @@ -1389,7 +7654,7 @@

    Return Value

    Declaration

    Swift

    -
    public static func >=(lhs: Constant, rhs: Constant) -> Constant<Signed>
    +
    public static func >= (lhs: Constant, rhs: Constant) -> Constant<Signed>
    @@ -1432,23 +7697,12 @@

    Return Value

  • - - -
    - -
    • - - - !(_:) + + + |(_:_:)
      @@ -1456,14 +7710,14 @@

      Logical Operations

      -

      A constant bitwise logical not with the given integral value as an operand.

      +

      A constant bitwise logical OR with the given values as operands.

      Declaration

      Swift

      -
      public static prefix func !(lhs: Constant) -> Constant
      +
      public static func | (lhs: Constant, rhs: Constant) -> Constant
      @@ -1474,12 +7728,24 @@

      Parameters

      - val + lhs
      -

      The value to negate.

      +

      The first operand.

      +
      + + + + + + rhs + + + +
      +

      The second operand.

      @@ -1488,8 +7754,8 @@

      Parameters

      Return Value

      -

      A constant value representing the logical negation of the given -operand.

      +

      A constant value representing the logical OR of the values of +the two given operands.

    @@ -1497,9 +7763,9 @@

    Return Value

  • - + - &(_:_:) + &(_:_:)
    @@ -1514,7 +7780,7 @@

    Return Value

    Declaration

    Swift

    -
    public static func &(lhs: Constant, rhs: Constant) -> Constant
    +
    public static func & (lhs: Constant, rhs: Constant) -> Constant
    @@ -1546,18 +7812,6 @@

    Parameters

    - - - - name - - - -
    -

    The name for the newly inserted instruction.

    -
    - - @@ -1572,9 +7826,9 @@

    Return Value

  • - - - |(_:_:) + + + <<(_:_:)
    @@ -1582,14 +7836,14 @@

    Return Value

    -

    A constant bitwise logical OR with the given values as operands.

    +

    A constant left-shift of the first value by the second amount.

    Declaration

    Swift

    -
    public static func |(lhs: Constant, rhs: Constant) -> Constant
    +
    public static func << (lhs: Constant, rhs: Constant) -> Constant
    @@ -1621,25 +7875,13 @@

    Parameters

    - - - - name - - - -
    -

    The name for the newly inserted instruction.

    -
    - -

    Return Value

    -

    A constant value representing the logical OR of the values of -the two given operands.

    +

    A constant value representing the value of the first operand +shifted left by the number of bits specified in the second operand.

    @@ -1647,9 +7889,9 @@

    Return Value

  • - - - ^(_:_:) + + + >>(_:_:)
    @@ -1657,14 +7899,14 @@

    Return Value

    -

    A constant bitwise logical exclusive OR with the given values as operands.

    +

    A constant right-shift of the first value by the second amount.

    Declaration

    Swift

    -
    public static func ^(lhs: Constant, rhs: Constant) -> Constant
    +
    public static func >> (lhs: Constant, rhs: Constant) -> Constant
    @@ -1701,8 +7943,8 @@

    Parameters

    Return Value

    -

    A constant value representing the exclusive OR of the values of -the two given operands.

    +

    A constant value representing the value of the first operand +shifted left by the number of bits specified in the second operand.

    @@ -1711,19 +7953,21 @@

    Return Value

    - - - -

    Bitshifting Operations

    -
    + + +
    + +

    Available where Repr: IntegralConstantRepresentation

    +

    +
    • - - - <<(_:_:) + + + !(_:)
      @@ -1731,14 +7975,14 @@

      Bitshifting Operations

      -

      A constant left-shift of the first value by the second amount.

      +

      A constant bitwise logical not with the given integral value as an operand.

      Declaration

      Swift

      -
      public static func <<(lhs: Constant, rhs: Constant) -> Constant
      +
      public prefix static func ! (lhs: Constant) -> Constant
      @@ -1749,24 +7993,12 @@

      Parameters

      - lhs - - - -
      -

      The first operand.

      -
      - - - - - - rhs + val
      -

      The second operand.

      +

      The value to negate.

      @@ -1775,8 +8007,39 @@

      Parameters

      Return Value

      -

      A constant value representing the value of the first operand -shifted left by the number of bits specified in the second operand.

      +

      A constant value representing the logical negation of the given +operand.

      +
      + +
    +
  • +
  • +
    + + + + undef(_:) + +
    +
    +
    +
    +
    +
    +

    Returns the special LLVM undef value for this type.

    + +

    The undef value can be used anywhere a constant is expected, and +indicates that the user of the value may receive an unspecified +bit-pattern.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public static func `undef`(_ ty: IntType) -> Constant
    + +
    @@ -1785,19 +8048,21 @@

    Return Value

    - - - -

    Conditional Operations

    -
    + + +
    + +

    Available where Repr == Floating

    +

    +
    • @@ -1805,65 +8070,108 @@

      Conditional Operations

      -

      A constant select using the given condition to select among two values.

      +

      Returns the special LLVM undef value for this type.

      + +

      The undef value can be used anywhere a constant is expected, and +indicates that the user of the value may receive an unspecified +bit-pattern.

      Declaration

      Swift

      -
      public static func select<T: ConstantRepresentation>(_ cond: Constant, then: Constant<T>, else: Constant<T>) -> Constant<T>
      +
      public static func `undef`(_ ty: FloatType) -> Constant
      -
      -

      Parameters

      - - - - - - - - - - - - - - - -
      - - cond - - -
      -

      The condition to evaluate. It must have type i1 or -be a vector of i1.

      -
      -
      - - then - - -
      -

      The value to select if the given condition is true.

      -
      -
      - - else - - -
      -

      The value to select if the given condition is false.

      -
      -
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Struct

    +

    +
    +
    +
      +
    • +
      + + + + undef(_:) + +
      +
      +
      +
      +
      +
      +

      Returns the special LLVM undef value for this type.

      + +

      The undef value can be used anywhere a constant is expected, and +indicates that the user of the value may receive an unspecified +bit-pattern.

      +
      -
      -

      Return Value

      -

      A constant value representing the constant value selected for -by the condition.

      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func `undef`(_ ty: StructType) -> Constant
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + + +
    + +

    Available where Repr == Vector

    +

    +
    +
    +
      +
    • +
      + + + + undef(_:) + +
      +
      +
      +
      +
      +
      +

      Returns the special LLVM undef value for this type.

      + +

      The undef value can be used anywhere a constant is expected, and +indicates that the user of the value may receive an unspecified +bit-pattern.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func `undef`(_ ty: VectorType) -> Constant
      + +
      @@ -1873,8 +8181,8 @@

      Return Value

    diff --git a/docs/Structs/DIBasicType.html b/docs/Structs/DIBasicType.html new file mode 100644 index 00000000..0a6d0565 --- /dev/null +++ b/docs/Structs/DIBasicType.html @@ -0,0 +1,660 @@ + + + + DIBasicType Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    DIBasicType

    +
    +
    + +
    public struct DIBasicType : DIType
    + +
    +
    +

    DIBasicType nodes represent primitive types, such as int, bool and +float.

    + +

    Basic types carry an encoding describing the details of the type to +influence how it is presented in debuggers. LLVM currently supports +specific DWARF “Attribute Type Encodings” that are enumerated in +DIAttributeTypeEncoding.

    + +
    +
    +
    +
      +
    • +
      + + + + asMetadata() + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func asMetadata() -> LLVMMetadataRef
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(llvm:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(llvm: LLVMMetadataRef)
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/DIFlags.html b/docs/Structs/DIFlags.html new file mode 100644 index 00000000..98b245d2 --- /dev/null +++ b/docs/Structs/DIFlags.html @@ -0,0 +1,1448 @@ + + + + DIFlags Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    DIFlags

    +
    +
    + +
    public struct DIFlags : OptionSet
    + +
    +
    +

    Enumerates a set of flags that can be applied to metadata nodes to change +their interpretation at compile time or attach additional semantic +significance at runtime.

    + +
    +
    +
    +
      +
    • +
      + + + + rawValue + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public let rawValue: LLVMDIFlags.RawValue
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(rawValue:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(rawValue: LLVMDIFlags.RawValue)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + private + +
      +
      +
      +
      +
      +
      +

      Denotes the private visibility attribute.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let `private`: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + protected + +
      +
      +
      +
      +
      +
      +

      Denotes the protected visibility attribute.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let protected: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + public + +
      +
      +
      +
      +
      +
      +

      Denotes the public visibility attribute.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let `public`: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + forwardDeclaration + +
      +
      +
      +
      +
      +
      +

      Denotes a forward declaration.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let forwardDeclaration: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + appleBlock + +
      +
      +
      +
      +
      +
      +

      Denotes a block object.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let appleBlock: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + virtual + +
      +
      +
      +
      +
      +
      +

      Denotes a virtual function or dynamic dispatch.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let virtual: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + artificial + +
      +
      +
      +
      +
      +
      +

      Denotes a compiler-generated declaration that may not appear in source.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let artificial: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + explicit + +
      +
      +
      +
      +
      +
      +

      Denotes an explicit-annotated declaration.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let explicit: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + prototyped + +
      +
      +
      +
      +
      +
      +

      Denotes a prototype declaration.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let prototyped: DIFlags
      + +
      +
      +
      +
      +
    • +
    • + +
      +
      +
      +
      +
      +

      Denotes an Objective-C class whose definition is visible to the compiler.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let objectiveCClassComplete: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + objectPointer + +
      +
      +
      +
      +
      +
      +

      Denotes a pointer value that is known to point to a C++ or Objective-C +object - usually self or this.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let objectPointer: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + vector + +
      +
      +
      +
      +
      +
      +

      Denotes a vector type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let vector: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + staticMember + +
      +
      +
      +
      +
      +
      +

      Denotes a static member.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let staticMember: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + lValueReference + +
      +
      +
      +
      +
      +
      +

      Denotes an lvalue reference.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let lValueReference: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + rValueReference + +
      +
      +
      +
      +
      +
      +

      Denotes an rvalue reference.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let rValueReference: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + singleInheritance + +
      +
      +
      +
      +
      +
      +

      Denotes a class type that is part of a single inheritance class hierarchy. +This flag is required to be set for CodeView compatibility.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let singleInheritance: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + multipleInheritance + +
      +
      +
      +
      +
      +
      +

      Denotes a class type that is part of a multiple inheritance class +hierarchy. This flag is required to be set for CodeView compatibility.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let multipleInheritance: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + virtualInheritance + +
      +
      +
      +
      +
      +
      +

      Denotes a class type whose inheritance involves virtual members. This +flag is required to be set for CodeView compatibility.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let virtualInheritance: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + introducedVirtual + +
      +
      +
      +
      +
      +
      +

      Denotes a class type that introduces virtual members. This is needed for +the MS C++ ABI does not include all virtual methods from non-primary bases +in the vtable for the most derived class

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let introducedVirtual: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + bitField + +
      +
      +
      +
      +
      +
      +

      Denotes a bitfield type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let bitField: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + noReturn + +
      +
      +
      +
      +
      +
      +

      Denotes a noreturn function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let noReturn: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + passByValue + +
      +
      +
      +
      +
      +
      +

      Denotes a parameter that is passed by value according to the target’s +calling convention.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let passByValue: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + passByReference + +
      +
      +
      +
      +
      +
      +

      Denotes a parameter that is passed by indirect reference according to the +target’s calling convention.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let passByReference: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + enumClass + +
      +
      +
      +
      +
      +
      +

      Denotes a “fixed enum” type e.g. a C++ enum class.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let enumClass: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + thunk + +
      +
      +
      +
      +
      +
      +

      Denotes a thunk function.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let thunk: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + nonTrivial + +
      +
      +
      +
      +
      +
      +

      Denotes a class that has a non-trivial default constructor or is not trivially copiable.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let nonTrivial: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + indirectVirtualBase + +
      +
      +
      +
      +
      +
      +

      Denotes an indirect virtual base class.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let indirectVirtualBase: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + accessibility + +
      +
      +
      +
      +
      +
      +

      The mask for public, private, and protected accessibility.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let accessibility: DIFlags
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + pointerToMemberRep + +
      +
      +
      +
      +
      + +
      +

      Declaration

      +
      +

      Swift

      +
      public static let pointerToMemberRep: DIFlags
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/DISubroutineType.html b/docs/Structs/DISubroutineType.html new file mode 100644 index 00000000..dab46198 --- /dev/null +++ b/docs/Structs/DISubroutineType.html @@ -0,0 +1,658 @@ + + + + DISubroutineType Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    DISubroutineType

    +
    +
    + +
    public struct DISubroutineType : DIType
    + +
    +
    +

    DISubroutineType nodes represent subroutine types.

    + +

    Subroutine types are meant to mirror their formal declarations in source: +arguments are represented in order. The return type is optional and meant +to represent the concept of void in C-like languages.

    + +
    +
    +
    +
      +
    • +
      + + + + asMetadata() + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func asMetadata() -> LLVMMetadataRef
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(llvm:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(llvm: LLVMMetadataRef)
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/DebugLocation.html b/docs/Structs/DebugLocation.html new file mode 100644 index 00000000..1f5e030a --- /dev/null +++ b/docs/Structs/DebugLocation.html @@ -0,0 +1,739 @@ + + + + DebugLocation Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    DebugLocation

    +
    +
    + +
    public struct DebugLocation : IRMetadata
    + +
    +
    +

    A DebugLocation represents a location in source.

    + +

    Debug locations are de-duplicated by file and line. If more than one +location inside a given scope needs to share a line, a discriminator value +must be set or those locations will be considered equivalent.

    + +
    +
    +
    +
      +
    • +
      + + + + asMetadata() + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func asMetadata() -> LLVMMetadataRef
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + line + +
      +
      +
      +
      +
      +
      +

      Retrieves the line described by this location.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var line: Int { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + column + +
      +
      +
      +
      +
      +
      +

      Retrieves the column described by this location.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var column: Int { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + scope + +
      +
      +
      +
      +
      +
      +

      Retrieves the enclosing scope containing this location.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var scope: DIScope { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(llvm:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(llvm: LLVMMetadataRef)
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/EnumAttribute.html b/docs/Structs/EnumAttribute.html new file mode 100644 index 00000000..c6eb23af --- /dev/null +++ b/docs/Structs/EnumAttribute.html @@ -0,0 +1,656 @@ + + + + EnumAttribute Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    EnumAttribute

    +
    +
    + +
    public struct EnumAttribute : Attribute
    + +
    +
    +

    An “enum” (a.k.a. target-independent) attribute.

    + +
    +
    +
    +
      +
    • +
      + + + + value + +
      +
      +
      +
      +
      +
      +

      The value of the attribute.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var value: UInt64 { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + asLLVM() + +
      +
      +
      +
      +
      +
      +

      Retrieves the underlying LLVM attribute object.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func asLLVM() -> LLVMAttributeRef
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/ExpressionMetadata.html b/docs/Structs/ExpressionMetadata.html new file mode 100644 index 00000000..071443f0 --- /dev/null +++ b/docs/Structs/ExpressionMetadata.html @@ -0,0 +1,665 @@ + + + + ExpressionMetadata Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    ExpressionMetadata

    +
    +
    + +
    public struct ExpressionMetadata : IRMetadata
    + +
    +
    +

    ExpressionMetadata nodes represent expressions that are inspired by the +DWARF expression language. They are used in debug intrinsics (such as +llvm.dbg.declare and llvm.dbg.value) to describe how the referenced LLVM +variable relates to the source language variable.

    + +

    Debug intrinsics are interpreted left-to-right: start by pushing the +value/address operand of the intrinsic onto a stack, then repeatedly push +and evaluate opcodes from the ExpressionMetadata until the final variable +description is produced.

    + +

    Though DWARF supports hundreds of expressions, LLVM currently implements +a very limited subset.

    + +
    +
    +
    +
      +
    • +
      + + + + asMetadata() + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func asMetadata() -> LLVMMetadataRef
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(llvm:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(llvm: LLVMMetadataRef)
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/FileMetadata.html b/docs/Structs/FileMetadata.html new file mode 100644 index 00000000..3396bd16 --- /dev/null +++ b/docs/Structs/FileMetadata.html @@ -0,0 +1,738 @@ + + + + FileMetadata Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    FileMetadata

    +
    +
    + +
    public struct FileMetadata : DIScope
    + +
    +
    +

    FileMetadata nodes represent files.

    + +

    The file name does not necessarily have to be a proper file path. For +example, it can include additional slash-separated path components.

    + +
    +
    +
    +
      +
    • +
      + + + + asMetadata() + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func asMetadata() -> LLVMMetadataRef
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(llvm:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(llvm: LLVMMetadataRef)
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + name + +
      +
      +
      +
      +
      +
      +

      Retrieves the name of this file

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var name: String { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + directory + +
      +
      +
      +
      +
      +
      +

      Retrieves the directory of this file

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var directory: String { get }
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + source + +
      +
      +
      +
      +
      +
      +

      Retrieves the source text of this file.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var source: String { get }
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/FloatType.html b/docs/Structs/FloatType.html new file mode 100644 index 00000000..3a30cd55 --- /dev/null +++ b/docs/Structs/FloatType.html @@ -0,0 +1,1066 @@ + + + + FloatType Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    FloatType

    +
    +
    + +
    public struct FloatType : IRType
    +
    extension FloatType: Equatable
    + +
    +
    +

    FloatType enumerates representations of a floating value of a particular +bit width and semantics.

    + +
    +
    +
    +
      +
    • +
      + + + + kind + +
      +
      +
      +
      +
      +
      +

      The kind of floating point type this is

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public var kind: Kind
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + context + +
      +
      +
      +
      +
      +
      +

      Returns the context associated with this type.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public let context: Context
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(kind:in:) + +
      +
      +
      +
      +
      +
      +

      Creates a float type of a particular kind

      + + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(kind: Kind, in context: Context = Context.global)
      + +
      +
      +
      +

      Parameters

      + + + + + + + + + + + +
      + + kind + + +
      +

      The kind of floating point type to create

      +
      +
      + + context + + +
      +

      The context to create this type in

      +
      +
      +
      +
      +
      +
    • +
    • +
      + + + + Kind + +
      +
      +
      +
      +
      +
      +

      Enumerates the bitwidth and kind of supported floating point types.

      + + See more +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public enum Kind
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + half + +
      +
      +
      +
      +
      +
      +

      16-bit floating point value in the global context

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let half: FloatType
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + float + +
      +
      +
      +
      +
      +
      +

      32-bit floating point value in the global context

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let float: FloatType
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + double + +
      +
      +
      +
      +
      +
      +

      64-bit floating point value in the global context

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let double: FloatType
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + x86FP80 + +
      +
      +
      +
      +
      +
      +

      80-bit floating point value (X87) in the global context

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let x86FP80: FloatType
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + fp128 + +
      +
      +
      +
      +
      +
      +

      128-bit floating point value (112-bit mantissa) in the global context

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let fp128: FloatType
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ppcFP128 + +
      +
      +
      +
      +
      +
      +

      128-bit floating point value (two 64-bits) in the global context

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static let ppcFP128: FloatType
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + constant(_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant floating value of this type from a Swift Double value.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func constant(_ value: Double) -> Constant<Floating>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + value + + +
      +

      A Swift double value.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing a floating point constant initialized +with the given Swift double value.

      +
      +
      +
      +
    • +
    • +
      + + + + constant(_:) + +
      +
      +
      +
      +
      +
      +

      Creates a constant floating value of this type parsed from a string.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func constant(_ value: String) -> Constant<Floating>
      + +
      +
      +
      +

      Parameters

      + + + + + + + +
      + + value + + +
      +

      A string value containing a float.

      +
      +
      +
      +
      +

      Return Value

      +

      A value representing a constant initialized with the result of +parsing the string as a floating point number.

      +
      +
      +
      +
    • +
    • +
      + + + + asLLVM() + +
      +
      +
      +
      +
      +
      +

      Retrieves the underlying LLVM type object.

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func asLLVM() -> LLVMTypeRef
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ==(_:_:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public static func == (lhs: FloatType, rhs: FloatType) -> Bool
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/FloatType/Kind.html b/docs/Structs/FloatType/Kind.html new file mode 100644 index 00000000..50080024 --- /dev/null +++ b/docs/Structs/FloatType/Kind.html @@ -0,0 +1,764 @@ + + + + Kind Enumeration Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    Kind

    +
    +
    + +
    public enum Kind
    + +
    +
    +

    Enumerates the bitwidth and kind of supported floating point types.

    + +
    +
    +
    +
      +
    • +
      + + + + half + +
      +
      +
      +
      +
      +
      +

      16-bit floating point value

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case half
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + float + +
      +
      +
      +
      +
      +
      +

      32-bit floating point value

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case float
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + double + +
      +
      +
      +
      +
      +
      +

      64-bit floating point value

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case double
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + x86FP80 + +
      +
      +
      +
      +
      +
      +

      80-bit floating point value (X87)

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case x86FP80
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + fp128 + +
      +
      +
      +
      +
      +
      +

      128-bit floating point value (112-bit mantissa)

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case fp128
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + ppcFP128 + +
      +
      +
      +
      +
      +
      +

      128-bit floating point value (two 64-bits)

      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      case ppcFP128
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/FunctionMetadata.html b/docs/Structs/FunctionMetadata.html new file mode 100644 index 00000000..84fd6ba9 --- /dev/null +++ b/docs/Structs/FunctionMetadata.html @@ -0,0 +1,655 @@ + + + + FunctionMetadata Structure Reference + + + + + + + + + + + + + +
    +
    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    +
    +
    +
    + +
    +
    + +
    +
    +
    +

    FunctionMetadata

    +
    +
    + +
    public struct FunctionMetadata : DIScope
    + +
    +
    +

    NameSpaceMetadata nodes represent subroutines in the source program. +They are attached to corresponding LLVM IR functions.

    + +
    +
    +
    +
      +
    • +
      + + + + asMetadata() + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public func asMetadata() -> LLVMMetadataRef
      + +
      +
      +
      +
      +
    • +
    • +
      + + + + init(llvm:) + +
      +
      +
      +
      +
      +
      + +
      +
      +

      Declaration

      +
      +

      Swift

      +
      public init(llvm: LLVMMetadataRef)
      + +
      +
      +
      +
      +
    • +
    +
    +
    +
    + +
    +
    + + + diff --git a/docs/Structs/FunctionType.html b/docs/Structs/FunctionType.html index d8331402..b44104a4 100644 --- a/docs/Structs/FunctionType.html +++ b/docs/Structs/FunctionType.html @@ -1,27 +1,35 @@ - FunctionType Struct Reference + FunctionType Structure Reference + + + - +
    -

    Docs (100% documented)

    +

    LLVM 0.8 Docs (100% documented)

    +

    +

    + +
    +

    @@ -30,30 +38,93 @@