@@ -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+
400588extension Bool {
401589 internal var llvm : LLVMBool {
402590 return self ? 1 : 0
0 commit comments