22import cllvm
33#endif
44
5- /// Enumerates the attributes of LLVM functions and function parameters.
6- public enum FunctionAttribute : String {
5+ /// Enumerates the kinds of attributes of LLVM functions and function parameters.
6+ public enum AttributeKind : String {
77 /// This attribute indicates that, when emitting the prologue and epilogue,
88 /// the backend should forcibly align the stack pointer.
99 case alignstack
@@ -81,13 +81,6 @@ public enum FunctionAttribute: String {
8181 /// otherwise do optimizations specifically to reduce code size as long as
8282 /// they do not significantly impact runtime performance.
8383 case optsize
84- /// This attribute tells the code generator that the code generated for this
85- /// function needs to follow certain conventions that make it possible for a
86- /// runtime function to patch over it later.
87- case patchableFunction = " patchable-function "
88- /// This attribute indicates that the function will trigger a guard region in
89- /// the end of the stack.
90- case probeStack = " probe-stack "
9184 /// This attribute indicates that the function computes its result (or
9285 /// decides to unwind an exception) based strictly on its arguments, without
9386 /// dereferencing any pointer arguments or otherwise accessing any mutable
@@ -97,11 +90,6 @@ public enum FunctionAttribute: String {
9790 /// pointer arguments (including byval arguments) or otherwise modify any
9891 /// state (e.g. memory, control registers, etc) visible to caller functions.
9992 case readonly
100- /// This attribute controls the behavior of stack probes: either the
101- /// "probe-stack" attribute, or ABI-required stack probes, if any.
102- case stackProbleSize = " stack-probe-size "
103- /// This attribute disables ABI-required stack probes, if any.
104- case noStackArgProbe = " no-stack-arg-probe "
10593 /// This attribute indicates that the function may write to but does not read
10694 /// read from memory.
10795 case writeonly
@@ -142,9 +130,6 @@ public enum FunctionAttribute: String {
142130 /// This attribute indicates that the function was called from a scope that
143131 /// requires strict floating point semantics.
144132 case strictfp
145- /// This attribute indicates that the function will delegate to some other
146- /// function with a tail call.
147- case thunk
148133 /// This attribute indicates that the ABI being targeted requires that an
149134 /// unwind table entry be produced for this function even if we can show
150135 /// that no exceptions passes by it.
@@ -201,7 +186,7 @@ public enum FunctionAttribute: String {
201186 case swifterror
202187
203188 /// ID of the attribute.
204- internal var kindID : UInt32 {
189+ internal var id : UInt32 {
205190 return LLVMGetEnumAttributeKindForName ( rawValue, rawValue. count)
206191 }
207192}
@@ -236,25 +221,154 @@ public enum AttributeIndex: ExpressibleByIntegerLiteral, RawRepresentable {
236221 }
237222}
238223
224+ /// An LLVM attribute.
225+ public protocol Attribute {
226+ var name : String { get }
227+ func asLLVM( ) -> LLVMAttributeRef
228+ }
229+
230+ /// An "enum" (a.k.a. target-independent) attribute.
231+ public struct EnumAttribute : Attribute {
232+ internal let llvm : LLVMAttributeRef
233+ internal init ( llvm: LLVMAttributeRef ) {
234+ self . llvm = llvm
235+ }
236+
237+ /// The kind ID of the attribute.
238+ internal var kindID : UInt32 {
239+ return LLVMGetEnumAttributeKind ( llvm)
240+ }
241+
242+ /// The name of the attribute's kind.
243+ public var name : String {
244+ return " "
245+ }
246+
247+ /// The value of the attribute.
248+ public var value : UInt64 {
249+ return LLVMGetEnumAttributeValue ( llvm)
250+ }
251+
252+ /// Retrieves the underlying LLVM attribute object.
253+ public func asLLVM( ) -> LLVMAttributeRef {
254+ return llvm
255+ }
256+ }
257+
258+ /// A "string" (a.k.a. target-dependent) attribute.
259+ public struct StringAttribute : Attribute {
260+ internal let llvm : LLVMAttributeRef
261+ internal init ( llvm: LLVMAttributeRef ) {
262+ self . llvm = llvm
263+ }
264+
265+ /// The name of the attribute.
266+ public var name : String {
267+ var length : UInt32 = 0
268+ let cstring = LLVMGetStringAttributeKind ( llvm, & length)
269+ return String . init ( cString: cstring!)
270+ }
271+
272+ /// The value of the attribute.
273+ public var value : String {
274+ var length : UInt32 = 0
275+ let cstring = LLVMGetStringAttributeValue ( llvm, & length)
276+ return String . init ( cString: cstring!)
277+ }
278+
279+ /// Retrieves the underlying LLVM attribute object.
280+ public func asLLVM( ) -> LLVMAttributeRef {
281+ return llvm
282+ }
283+ }
284+
239285extension Function {
240- /// Adds an attribute to the function, its return value or its parameters.
286+ /// Adds an enum attribute to the function, its return value or one of its
287+ /// parameters.
241288 ///
242- /// - parameter attr : The attribute to add.
289+ /// - parameter attrKind : The kind of the attribute to add.
243290 /// - parameter value: The optional value of the attribute.
244291 /// - parameter index: The index representing the function, its return value
245292 /// or one of its parameters.
246- public func addAttribute( _ attr: FunctionAttribute , value: UInt64 = 0 , to index: AttributeIndex ) {
293+ @discardableResult
294+ public func addAttribute( _ attrKind: AttributeKind , value: UInt64 = 0 , to index: AttributeIndex ) -> EnumAttribute {
247295 let ctx = LLVMGetModuleContext ( LLVMGetGlobalParent ( llvm) )
248- let attrRef = LLVMCreateEnumAttribute ( ctx, attr . kindID , value)
296+ let attrRef = LLVMCreateEnumAttribute ( ctx, attrKind . id , value)
249297 LLVMAddAttributeAtIndex ( llvm, index. rawValue, attrRef)
298+ return EnumAttribute ( llvm: attrRef!)
250299 }
251300
252- /// Removes an attribute from the function.
301+ /// Adds a string attribute to the function, its return value or one of its
302+ /// parameters.
303+ ///
304+ /// - parameter name: The name of the attribute to add.
305+ /// - parameter value: The optional value of the attribute.
306+ /// - parameter index: The index representing the function, its return value
307+ /// or one of its parameters.
308+ @discardableResult
309+ public func addAttribute( _ name: String , value: String = " " , to index: AttributeIndex ) -> StringAttribute {
310+ let ctx = LLVMGetModuleContext ( LLVMGetGlobalParent ( llvm) )
311+ let attrRef = name. withCString { cname -> LLVMAttributeRef ! in
312+ return value. withCString { cvalue in
313+ return LLVMCreateStringAttribute ( ctx, cname, UInt32 ( name. count) , cvalue, UInt32 ( value. count) )
314+ }
315+ }
316+ LLVMAddAttributeAtIndex ( llvm, index. rawValue, attrRef)
317+ return StringAttribute ( llvm: attrRef!)
318+ }
319+
320+ /// Removes an attribute from the function, its return value or one of its
321+ /// parameters.
253322 ///
254323 /// - parameter attr: The attribute to remove.
255324 /// - parameter index: The index representing the function, its return value
256325 /// or one of its parameters.
257- public func removeAttribute( _ attr: FunctionAttribute , value: UInt64 = 0 , from index: AttributeIndex ) {
258- LLVMRemoveEnumAttributeAtIndex ( llvm, index. rawValue, attr. kindID)
326+ public func removeAttribute( _ attr: Attribute , from index: AttributeIndex ) {
327+ switch attr {
328+ case let enumAttr as EnumAttribute :
329+ LLVMRemoveEnumAttributeAtIndex ( llvm, index. rawValue, enumAttr. kindID)
330+ case let stringAttr as StringAttribute :
331+ var length : UInt32 = 0
332+ let cstring = LLVMGetStringAttributeKind ( stringAttr. llvm, & length)
333+ LLVMRemoveStringAttributeAtIndex ( llvm, index. rawValue, cstring, length)
334+ default :
335+ fatalError ( )
336+ }
337+ }
338+
339+ /// Removes an enum attribute from the function, its return value or one of
340+ /// its parameters.
341+ ///
342+ /// - parameter attr: The kind of the attribute to remove.
343+ /// - parameter index: The index representing the function, its return value
344+ /// or one of its parameters.
345+ public func removeAttribute( _ attrKind: AttributeKind , from index: AttributeIndex ) {
346+ LLVMRemoveEnumAttributeAtIndex ( llvm, index. rawValue, attrKind. id)
347+ }
348+
349+ /// Removes a string attribute from the function, its return value or one of
350+ /// its parameters.
351+ ///
352+ /// - parameter name: The name of the attribute to remove.
353+ /// - parameter index: The index representing the function, its return value
354+ /// or one of its parameters.
355+ public func removeAttribute( _ name: String , from index: AttributeIndex ) {
356+ name. withCString {
357+ LLVMRemoveStringAttributeAtIndex ( llvm, index. rawValue, $0, UInt32 ( name. count) )
358+ }
359+ }
360+
361+ /// Gets the attributes of the function, its return value or its parameters.
362+ public func attributes( at index: AttributeIndex ) -> [ Attribute ] {
363+ let attrCount = LLVMGetAttributeCountAtIndex ( llvm, index. rawValue)
364+ var attrRefs : [ LLVMAttributeRef ? ] = Array ( repeating: nil , count: Int ( attrCount) )
365+ LLVMGetAttributesAtIndex ( llvm, index. rawValue, & attrRefs)
366+ return attrRefs. map { attrRef -> Attribute in
367+ if LLVMIsEnumAttribute ( attrRef) != 0 {
368+ return EnumAttribute ( llvm: attrRef!)
369+ } else {
370+ return StringAttribute ( llvm: attrRef!)
371+ }
372+ }
259373 }
260374}
0 commit comments