@@ -79,3 +79,140 @@ extension IRGlobal {
7979 LLVMDeleteGlobal ( self . asLLVM ( ) )
8080 }
8181}
82+
83+ // MARK: Global Metadata
84+
85+ extension IRGlobal {
86+ /// Retrieves all metadata entries attached to this global value.
87+ public var metadata : AttachedMetadata {
88+ var count = 0
89+ let ptr = LLVMGlobalCopyAllMetadata ( self . asLLVM ( ) , & count)
90+ return AttachedMetadata ( llvm: ptr, bounds: count)
91+ }
92+
93+ /// Sets a metadata attachment, erasing the existing metadata attachment if
94+ /// it already exists for the given kind.
95+ ///
96+ /// - Parameters:
97+ /// - metadata: The metadata to attach to this global value.
98+ /// - kind: The kind of metadata to attach.
99+ public func addMetadata( _ metadata: IRMetadata , kind: UInt32 ) {
100+ LLVMGlobalSetMetadata ( self . asLLVM ( ) , kind, metadata. asMetadata ( ) )
101+ }
102+
103+ /// Removes all metadata attachments from this value.
104+ public func removeAllMetadata( ) {
105+ LLVMGlobalClearMetadata ( self . asLLVM ( ) )
106+ }
107+
108+ /// Erases a metadata attachment of the given kind if it exists.
109+ ///
110+ /// - Parameter kind: The kind of the metadata to remove.
111+ public func eraseAllMetadata( of kind: UInt32 ) {
112+ LLVMGlobalEraseMetadata ( self . asLLVM ( ) , kind)
113+ }
114+ }
115+
116+ /// Represents a sequence of metadata entries attached to a global value that
117+ /// are uniqued by kind.
118+ public class AttachedMetadata {
119+ /// Metadata kinds that are known to LLVM.
120+ public enum PinnedMetadataKind : UInt32 {
121+ /// "dbg"
122+ case dbg = 0
123+ /// "tbaa"
124+ case tbaa = 1
125+ /// "prof"
126+ case prof = 2
127+ /// "fpmath"
128+ case fpmath = 3
129+ /// "range"
130+ case range = 4
131+ /// "tbaa.struct"
132+ case tbaaStruct = 5
133+ /// "invariant.load"
134+ case invariantLoad = 6
135+ /// "alias.scope"
136+ case alias_scope = 7
137+ /// "noalias",
138+ case noalias = 8
139+ /// "nontemporal"
140+ case nontemporal = 9
141+ /// "llvm.mem.parallel_loop_access"
142+ case memParallelLoopAccess = 10
143+ /// "nonnull"
144+ case nonnull = 11
145+ /// "dereferenceable"
146+ case dereferenceable = 12
147+ /// "dereferenceable_or_null"
148+ case dereferenceable_or_null = 13
149+ /// "make.implicit"
150+ case makeImplicit = 14
151+ /// "unpredictable"
152+ case unpredictable = 15
153+ /// "invariant.group"
154+ case invariantGroup = 16
155+ /// "align"
156+ case align = 17
157+ /// "llvm.loop"
158+ case loop = 18
159+ /// "type"
160+ case type = 19
161+ /// "section_prefix"
162+ case sectionPrefix = 20
163+ /// "absolute_symbol"
164+ case absoluteSymbol = 21
165+ /// "associated"
166+ case associated = 22
167+ /// "callees"
168+ case callees = 23
169+ /// "irr_loop"
170+ case irrLoop = 24
171+ /// "llvm.access.group"
172+ case accessGroup = 25
173+ // "callback"
174+ case callback = 26
175+ }
176+
177+ /// Represents an entry in the module flags structure.
178+ public struct Entry {
179+ fileprivate let base : AttachedMetadata
180+ fileprivate let index : UInt32
181+
182+ /// The metadata kind associated with this global metadata.
183+ public var kind : UInt32 {
184+ return LLVMValueMetadataEntriesGetKind ( self . base. llvm, self . index)
185+ }
186+
187+ /// The metadata value associated with this entry.
188+ public var metadata : IRMetadata {
189+ return AnyMetadata ( llvm: LLVMValueMetadataEntriesGetMetadata ( self . base. llvm, self . index) )
190+ }
191+ }
192+
193+ private let llvm : OpaquePointer ?
194+ private let bounds : Int
195+ fileprivate init ( llvm: OpaquePointer ? , bounds: Int ) {
196+ self . llvm = llvm
197+ self . bounds = bounds
198+ }
199+
200+ deinit {
201+ guard let ptr = llvm else { return }
202+ LLVMDisposeValueMetadataEntries ( ptr)
203+ }
204+
205+ /// Retrieves a flag at the given index.
206+ ///
207+ /// - Parameter index: The index to retrieve.
208+ ///
209+ /// - Returns: An entry describing the flag at the given index.
210+ public subscript( _ index: Int ) -> Entry {
211+ precondition ( index >= 0 && index < self . bounds, " Index out of bounds " )
212+ return Entry ( base: self , index: UInt32 ( index) )
213+ }
214+
215+ public var count : Int {
216+ return self . bounds
217+ }
218+ }
0 commit comments