@@ -324,7 +324,7 @@ extension Module {
324324 /// - parameter name: The name of the function to create.
325325 ///
326326 /// - returns: A representation of the newly created function with the given
327- /// name or nil if such a representation could not be created.
327+ /// name or nil if such a representation could not be created.
328328 public func function( named name: String ) -> Function ? {
329329 guard let fn = LLVMGetNamedFunction ( llvm, name) else { return nil }
330330 return Function ( llvm: fn)
@@ -432,6 +432,159 @@ extension Module {
432432 }
433433}
434434
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+
435588extension Bool {
436589 internal var llvm : LLVMBool {
437590 return self ? 1 : 0
0 commit comments