Skip to content

Commit 993c0f3

Browse files
authored
Merge pull request #172 from CodaFi/christmas-declarations
Miscellaneous missing bindings from LLVM 7.0
2 parents 98b95ab + 79f974d commit 993c0f3

File tree

5 files changed

+278
-1
lines changed

5 files changed

+278
-1
lines changed

Sources/LLVM/Alias.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,22 @@ public struct Alias: IRGlobal {
1111
public func asLLVM() -> LLVMValueRef {
1212
return llvm
1313
}
14+
15+
/// Access the target value of this alias.
16+
public var aliasee: IRValue {
17+
get { return LLVMAliasGetAliasee(llvm) }
18+
set { LLVMAliasSetAliasee(llvm, newValue.asLLVM()) }
19+
}
20+
21+
/// Retrieves the previous alias in the module, if there is one.
22+
public func previous() -> Alias? {
23+
guard let previous = LLVMGetPreviousGlobalAlias(llvm) else { return nil }
24+
return Alias(llvm: previous)
25+
}
26+
27+
/// Retrieves the next alias in the module, if there is one.
28+
public func next() -> Alias? {
29+
guard let next = LLVMGetNextGlobalAlias(llvm) else { return nil }
30+
return Alias(llvm: next)
31+
}
1432
}

Sources/LLVM/Module.swift

Lines changed: 189 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,29 @@ public final class Module: CustomStringConvertible {
230230
}
231231
}
232232

233+
/// Retrieves the sequence of aliases that make up this module.
234+
public var aliases: AnySequence<Alias> {
235+
var current = firstAlias
236+
return AnySequence<Alias> {
237+
return AnyIterator<Alias> {
238+
defer { current = current?.next() }
239+
return current
240+
}
241+
}
242+
}
243+
244+
/// Retrieves the first alias in this module, if there are any aliases.
245+
public var firstAlias: Alias? {
246+
guard let fn = LLVMGetFirstGlobalAlias(llvm) else { return nil }
247+
return Alias(llvm: fn)
248+
}
249+
250+
/// Retrieves the last alias in this module, if there are any aliases.
251+
public var lastAlias: Alias? {
252+
guard let fn = LLVMGetLastGlobalAlias(llvm) else { return nil }
253+
return Alias(llvm: fn)
254+
}
255+
233256
/// The current debug metadata version number.
234257
public static var debugMetadataVersion: UInt32 {
235258
return LLVMDebugMetadataVersion();
@@ -301,12 +324,24 @@ extension Module {
301324
/// - parameter name: The name of the function to create.
302325
///
303326
/// - returns: A representation of the newly created function with the given
304-
/// name or nil if such a representation could not be created.
327+
/// name or nil if such a representation could not be created.
305328
public func function(named name: String) -> Function? {
306329
guard let fn = LLVMGetNamedFunction(llvm, name) else { return nil }
307330
return Function(llvm: fn)
308331
}
309332

333+
/// Searches for and retrieves an alias with the given name in this module
334+
/// if that name references an existing alias.
335+
///
336+
/// - parameter name: The name of the alias to search for.
337+
///
338+
/// - returns: A representation of an alias with the given
339+
/// name or nil if no such named alias exists.
340+
public func alias(named name: String) -> Alias? {
341+
guard let alias = LLVMGetNamedGlobalAlias(llvm, name, name.count) else { return nil }
342+
return Alias(llvm: alias)
343+
}
344+
310345
/// Searches for and retrieves a comdat section with the given name in this
311346
/// module. If none is found, one with that name is created and returned.
312347
///
@@ -397,6 +432,159 @@ extension Module {
397432
}
398433
}
399434

435+
// MARK: Module Flags
436+
437+
extension Module {
438+
/// Represents flags that describe information about the module for use by
439+
/// an external entity e.g. the dynamic linker.
440+
///
441+
/// - Warning: Module flags are not a general runtime metadata infrastructure,
442+
/// and may be stripped by LLVM. As of the current release, LLVM hardcodes
443+
/// support for object-file emission of module flags related to
444+
/// Objective-C.
445+
public class Flags {
446+
/// Enumerates the supported behaviors for resolving collisions when two
447+
/// module flags share the same key. These collisions can occur when the
448+
/// different flags are inserted under the same key, or when modules
449+
/// containing flags under the same key are merged.
450+
public enum Behavior {
451+
/// Emits an error if two values disagree, otherwise the resulting value
452+
/// is that of the operands.
453+
case error
454+
/// Emits a warning if two values disagree. The result value will be the
455+
/// operand for the flag from the first module being linked.
456+
case warning
457+
/// Adds a requirement that another module flag be present and have a
458+
/// specified value after linking is performed. The value must be a
459+
/// metadata pair, where the first element of the pair is the ID of the
460+
/// module flag to be restricted, and the second element of the pair is
461+
/// the value the module flag should be restricted to. This behavior can
462+
/// be used to restrict the allowable results (via triggering of an error)
463+
/// of linking IDs with the **Override** behavior.
464+
case require
465+
/// Uses the specified value, regardless of the behavior or value of the
466+
/// other module. If both modules specify **Override**, but the values
467+
/// differ, an error will be emitted.
468+
case override
469+
/// Appends the two values, which are required to be metadata nodes.
470+
case append
471+
/// Appends the two values, which are required to be metadata
472+
/// nodes. However, duplicate entries in the second list are dropped
473+
/// during the append operation.
474+
case appendUnique
475+
476+
fileprivate init(raw: LLVMModuleFlagBehavior) {
477+
switch raw {
478+
case LLVMModuleFlagBehaviorError:
479+
self = .error
480+
case LLVMModuleFlagBehaviorWarning:
481+
self = .warning
482+
case LLVMModuleFlagBehaviorRequire:
483+
self = .require
484+
case LLVMModuleFlagBehaviorOverride:
485+
self = .override
486+
case LLVMModuleFlagBehaviorAppend:
487+
self = .append
488+
case LLVMModuleFlagBehaviorAppendUnique:
489+
self = .appendUnique
490+
default:
491+
fatalError("Unknown behavior kind")
492+
}
493+
}
494+
495+
fileprivate static let behaviorMapping: [Behavior: LLVMModuleFlagBehavior] = [
496+
.error: LLVMModuleFlagBehaviorError,
497+
.warning: LLVMModuleFlagBehaviorWarning,
498+
.require: LLVMModuleFlagBehaviorRequire,
499+
.override: LLVMModuleFlagBehaviorOverride,
500+
.append: LLVMModuleFlagBehaviorAppend,
501+
.appendUnique: LLVMModuleFlagBehaviorAppendUnique,
502+
]
503+
}
504+
505+
/// Represents an entry in the module flags structure.
506+
public struct Entry {
507+
fileprivate let base: Flags
508+
fileprivate let index: UInt32
509+
510+
/// The conflict behavior of this flag.
511+
public var behavior: Behavior {
512+
let raw = LLVMModuleFlagEntriesGetFlagBehavior(self.base.llvm, self.index)
513+
return Behavior(raw: raw)
514+
}
515+
516+
/// The key this flag was inserted with.
517+
public var key: String {
518+
var count = 0
519+
guard let key = LLVMModuleFlagEntriesGetKey(self.base.llvm, self.index, &count) else { return "" }
520+
return String(cString: key)
521+
}
522+
523+
/// The metadata value associated with this flag.
524+
public var metadata: IRMetadata {
525+
return AnyMetadata(llvm: LLVMModuleFlagEntriesGetMetadata(self.base.llvm, self.index))
526+
}
527+
}
528+
529+
private let llvm: OpaquePointer?
530+
private let bounds: Int
531+
fileprivate init(llvm: OpaquePointer?, bounds: Int) {
532+
self.llvm = llvm
533+
self.bounds = bounds
534+
}
535+
536+
deinit {
537+
guard let ptr = llvm else { return }
538+
LLVMDisposeModuleFlagsMetadata(ptr)
539+
}
540+
541+
/// Retrieves a flag at the given index.
542+
///
543+
/// - Parameter index: The index to retrieve.
544+
///
545+
/// - Returns: An entry describing the flag at the given index.
546+
public subscript(_ index: Int) -> Entry {
547+
precondition(index >= 0 && index < self.bounds, "Index out of bounds")
548+
return Entry(base: self, index: UInt32(index))
549+
}
550+
551+
public var count: Int {
552+
return self.bounds
553+
}
554+
}
555+
556+
/// Add a module-level flag to the module-level flags metadata.
557+
///
558+
/// - Parameters:
559+
/// - name: The key for this flag.
560+
/// - value: The metadata node to insert as the value for this flag.
561+
/// - behavior: The resolution strategy to apply should the key for this
562+
/// flag conflict with an existing flag.
563+
public func addFlag(named name: String, value: IRMetadata, behavior: Flags.Behavior) {
564+
let raw = Flags.Behavior.behaviorMapping[behavior]!
565+
LLVMAddModuleFlag(llvm, raw, name, name.count, value.asMetadata())
566+
}
567+
568+
/// A convenience for inserting constant values as module-level flags.
569+
///
570+
/// - Parameters:
571+
/// - name: The key for this flag.
572+
/// - value: The constant value to insert as the metadata for this flag.
573+
/// - behavior: The resolution strategy to apply should the key for this
574+
/// flag conflict with an existing flag.
575+
public func addFlag(named name: String, constant: IRConstant, behavior: Flags.Behavior) {
576+
let raw = Flags.Behavior.behaviorMapping[behavior]!
577+
LLVMAddModuleFlag(llvm, raw, name, name.count, LLVMValueAsMetadata(constant.asLLVM()))
578+
}
579+
580+
/// Retrieves the module-level flags, if they exist.
581+
public var flags: Flags? {
582+
var len = 0
583+
guard let raw = LLVMCopyModuleFlagsMetadata(llvm, &len) else { return nil }
584+
return Flags(llvm: raw, bounds: len)
585+
}
586+
}
587+
400588
extension Bool {
401589
internal var llvm: LLVMBool {
402590
return self ? 1 : 0

Sources/LLVM/PassManager.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public enum FunctionPass {
6060
case loopReroll
6161
/// This pass is a simple loop unrolling pass.
6262
case loopUnroll
63+
/// This pass is a simple loop unroll-and-jam pass.
64+
case loopUnrollAndJam
6365
/// This pass is a simple loop unswitching pass.
6466
case loopUnswitch
6567
/// This pass performs optimizations related to eliminating `memcpy` calls
@@ -198,6 +200,7 @@ public class FunctionPassManager {
198200
.loopRotate: LLVMAddLoopRotatePass,
199201
.loopReroll: LLVMAddLoopRerollPass,
200202
.loopUnroll: LLVMAddLoopUnrollPass,
203+
.loopUnrollAndJam: LLVMAddLoopUnrollAndJamPass,
201204
.loopUnswitch: LLVMAddLoopUnswitchPass,
202205
.memCpyOpt: LLVMAddMemCpyOptPass,
203206
.partiallyInlineLibCalls: LLVMAddPartiallyInlineLibCallsPass,
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import LLVM
2+
import XCTest
3+
import FileCheck
4+
import Foundation
5+
6+
class ModuleMetadataSpec : XCTestCase {
7+
func testAddModuleFlags() {
8+
XCTAssertTrue(fileCheckOutput(of: .stderr, withPrefixes: ["MODULE-FLAGS"]) {
9+
// MODULE-FLAGS: ; ModuleID = 'ModuleFlagsTest'
10+
let module = Module(name: "ModuleFlagsTest")
11+
// MODULE-FLAGS: !llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
12+
13+
// MODULE-FLAGS: !0 = !{i32 [[ERRVAL:\d+]], !"error", i32 [[ERRVAL]]}
14+
module.addFlag(named: "error", constant: IntType.int32.constant(1), behavior: .error)
15+
// MODULE-FLAGS-NEXT: !1 = !{i32 [[WARNVAL:\d+]], !"warning", i32 [[WARNVAL]]}
16+
module.addFlag(named: "warning", constant: IntType.int32.constant(2), behavior: .warning)
17+
// MODULE-FLAGS-NEXT: !2 = !{i32 [[REQUIREVAL:\d+]], !"require", i32 [[REQUIREVAL]]}
18+
module.addFlag(named: "require", constant: IntType.int32.constant(3), behavior: .require)
19+
// MODULE-FLAGS-NEXT: !3 = !{i32 [[OVERRIDEVAL:\d+]], !"override", i32 [[OVERRIDEVAL]]}
20+
module.addFlag(named: "override", constant: IntType.int32.constant(4), behavior: .override)
21+
// MODULE-FLAGS-NEXT: !4 = !{i32 [[APPVAL:\d+]], !"append", i32 [[APPVAL]]}
22+
module.addFlag(named: "append", constant: IntType.int32.constant(5), behavior: .append)
23+
// MODULE-FLAGS-NEXT: !5 = !{i32 [[APPUNIQVAL:\d+]], !"appendUnique", i32 [[APPUNIQVAL]]}
24+
module.addFlag(named: "appendUnique", constant: IntType.int32.constant(6), behavior: .appendUnique)
25+
26+
module.dump()
27+
})
28+
}
29+
30+
func testModuleRetrieveFlags() {
31+
let module = Module(name: "ModuleFlagsTest")
32+
module.addFlag(named: "error", constant: IntType.int32.constant(1), behavior: .error)
33+
module.addFlag(named: "warning", constant: IntType.int32.constant(2), behavior: .warning)
34+
module.addFlag(named: "require", constant: IntType.int32.constant(3), behavior: .require)
35+
module.addFlag(named: "override", constant: IntType.int32.constant(4), behavior: .override)
36+
module.addFlag(named: "append", constant: IntType.int32.constant(5), behavior: .append)
37+
module.addFlag(named: "appendUnique", constant: IntType.int32.constant(6), behavior: .appendUnique)
38+
39+
guard let flags = module.flags else {
40+
XCTFail()
41+
return
42+
}
43+
44+
XCTAssertEqual(flags.count, 6)
45+
46+
XCTAssertEqual(flags[0].behavior, .error)
47+
XCTAssertEqual(flags[1].behavior, .warning)
48+
XCTAssertEqual(flags[2].behavior, .require)
49+
XCTAssertEqual(flags[3].behavior, .override)
50+
XCTAssertEqual(flags[4].behavior, .append)
51+
XCTAssertEqual(flags[5].behavior, .appendUnique)
52+
53+
XCTAssertEqual(flags[0].key, "error")
54+
XCTAssertEqual(flags[1].key, "warning")
55+
XCTAssertEqual(flags[2].key, "require")
56+
XCTAssertEqual(flags[3].key, "override")
57+
XCTAssertEqual(flags[4].key, "append")
58+
XCTAssertEqual(flags[5].key, "appendUnique")
59+
}
60+
61+
#if !os(macOS)
62+
static var allTests = testCase([
63+
("testAddModuleFlags", testAddModuleFlags),
64+
("testModuleRetrieveFlags", testModuleRetrieveFlags),
65+
])
66+
#endif
67+
}

Tests/LinuxMain.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ XCTMain([
1414
// FIXME: These tests cannot run on Linux without SEGFAULT'ing.
1515
// JITSpec.allTests,
1616
ModuleLinkSpec.allTests,
17+
ModuleMetadataSpec.allTests,
1718
])
1819
#endif

0 commit comments

Comments
 (0)