@@ -4,77 +4,264 @@ import FileCheck
44import Foundation
55
66class IRAttributesSpec : XCTestCase {
7- func testIRAttributes( ) {
8- XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " FNATTR " ] ) {
9- // FNATTR: ; ModuleID = '[[ModuleName:IRBuilderTest]]'
10- // FNATTR-NEXT: source_filename = "[[ModuleName]]"
11- let module = Module ( name: " IRBuilderTest " )
12- let builder = IRBuilder ( module: module)
13- let fn = builder. addFunction ( " fn " ,
14- type: FunctionType ( argTypes: [ IntType . int32, IntType . int32] ,
15- returnType: IntType . int32) )
16-
17- // FNATTR: define i32 @fn(i32, i32) #0 {
18- fn. addAttribute ( . nounwind, to: . function)
19-
20- // FNATTR-NEXT: entry:
21- let entry = fn. appendBasicBlock ( named: " entry " )
22- builder. positionAtEnd ( of: entry)
23- // FNATTR-NEXT: ret i32 0
24- builder. buildRet ( IntType . int32. constant ( 0 ) )
25- // FNATTR-NEXT: }
26- // FNATTR: attributes #0 = { nounwind }
27- module. dump ( )
28- } )
29-
30- XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " RVATTR " ] ) {
31- // RVATTR: ; ModuleID = '[[ModuleName:IRBuilderTest]]'
32- // RVATTR-NEXT: source_filename = "[[ModuleName]]"
33- let module = Module ( name: " IRBuilderTest " )
34- let builder = IRBuilder ( module: module)
35- let fn = builder. addFunction ( " fn " ,
36- type: FunctionType ( argTypes: [ IntType . int32, IntType . int32] ,
37- returnType: IntType . int32) )
38-
39- // RVATTR: define signext i32 @fn(i32, i32) {
40- fn. addAttribute ( . signext, to: . returnValue)
41-
42- // RVATTR-NEXT: entry:
43- let entry = fn. appendBasicBlock ( named: " entry " )
44- builder. positionAtEnd ( of: entry)
45- // RVATTR-NEXT: ret i32 0
46- builder. buildRet ( IntType . int32. constant ( 0 ) )
47- // RVATTR-NEXT: }
48- module. dump ( )
49- } )
50-
51- XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " ARGATTR " ] ) {
52- // ARGATTR: ; ModuleID = '[[ModuleName:IRBuilderTest]]'
53- // ARGATTR-NEXT: source_filename = "[[ModuleName]]"
54- let module = Module ( name: " IRBuilderTest " )
55- let builder = IRBuilder ( module: module)
56- let fn = builder. addFunction ( " fn " ,
57- type: FunctionType ( argTypes: [ IntType . int32, IntType . int32] ,
58- returnType: IntType . int32) )
59-
60- // ARGATTR: define i32 @fn(i32 zeroext, i32 signext) {
61- fn. addAttribute ( . zeroext, to: . argument( 0 ) )
62- fn. addAttribute ( . signext, to: . argument( 1 ) )
63-
64- // ARGATTR-NEXT: entry:
65- let entry = fn. appendBasicBlock ( named: " entry " )
66- builder. positionAtEnd ( of: entry)
67- // ARGATTR-NEXT: ret i32 0
68- builder. buildRet ( IntType . int32. constant ( 0 ) )
69- // ARGATTR-NEXT: }
70- module. dump ( )
71- } )
7+ func testIRAttributes( ) {
8+ XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " FNATTR " ] ) {
9+ // FNATTR: ; ModuleID = '[[ModuleName:IRBuilderTest]]'
10+ // FNATTR-NEXT: source_filename = "[[ModuleName]]"
11+ let module = Module ( name: " IRBuilderTest " )
12+ let builder = IRBuilder ( module: module)
13+ let fn = builder. addFunction ( " fn " ,
14+ type: FunctionType ( argTypes: [ IntType . int32, IntType . int32] ,
15+ returnType: IntType . int32) )
16+
17+ // FNATTR: define i32 @fn(i32, i32) #0 {
18+ fn. addAttribute ( . nounwind, to: . function)
19+
20+ // FNATTR-NEXT: entry:
21+ let entry = fn. appendBasicBlock ( named: " entry " )
22+ builder. positionAtEnd ( of: entry)
23+ // FNATTR-NEXT: ret i32 0
24+ builder. buildRet ( IntType . int32. constant ( 0 ) )
25+ // FNATTR-NEXT: }
26+ // FNATTR: attributes #0 = { nounwind }
27+ module. dump ( )
28+ } )
29+
30+ XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " RVATTR " ] ) {
31+ // RVATTR: ; ModuleID = '[[ModuleName:IRBuilderTest]]'
32+ // RVATTR-NEXT: source_filename = "[[ModuleName]]"
33+ let module = Module ( name: " IRBuilderTest " )
34+ let builder = IRBuilder ( module: module)
35+ let fn = builder. addFunction ( " fn " ,
36+ type: FunctionType ( argTypes: [ IntType . int32, IntType . int32] ,
37+ returnType: IntType . int32) )
38+
39+ // RVATTR: define signext i32 @fn(i32, i32) {
40+ fn. addAttribute ( . signext, to: . returnValue)
41+
42+ // RVATTR-NEXT: entry:
43+ let entry = fn. appendBasicBlock ( named: " entry " )
44+ builder. positionAtEnd ( of: entry)
45+ // RVATTR-NEXT: ret i32 0
46+ builder. buildRet ( IntType . int32. constant ( 0 ) )
47+ // RVATTR-NEXT: }
48+ module. dump ( )
49+ } )
50+
51+ XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " ARGATTR " ] ) {
52+ // ARGATTR: ; ModuleID = '[[ModuleName:IRBuilderTest]]'
53+ // ARGATTR-NEXT: source_filename = "[[ModuleName]]"
54+ let module = Module ( name: " IRBuilderTest " )
55+ let builder = IRBuilder ( module: module)
56+ let i8ptr = PointerType ( pointee: IntType . int8)
57+ let fn = builder. addFunction ( " fn " ,
58+ type: FunctionType ( argTypes: [ IntType . int32, i8ptr] ,
59+ returnType: IntType . int32) )
60+
61+ // ARGATTR: define i32 @fn(i32 zeroext, i8* align 8) {
62+ fn. addAttribute ( . zeroext, to: . argument( 0 ) )
63+ fn. addAttribute ( . align, value: 8 , to: . argument( 1 ) )
64+
65+ // ARGATTR-NEXT: entry:
66+ let entry = fn. appendBasicBlock ( named: " entry " )
67+ builder. positionAtEnd ( of: entry)
68+ // ARGATTR-NEXT: ret i32 0
69+ builder. buildRet ( IntType . int32. constant ( 0 ) )
70+ // ARGATTR-NEXT: }
71+ module. dump ( )
72+ } )
73+ }
74+
75+ func testSetUnsetFunctionAttributes( ) {
76+ let module = Module ( name: " FNATTR " )
77+ let builder = IRBuilder ( module: module)
78+
79+ let i8ptr = PointerType ( pointee: IntType . int8)
80+ let fn = builder. addFunction ( " fn " ,
81+ type: FunctionType ( argTypes: [ i8ptr] , returnType: i8ptr) )
82+
83+ // MARK: Enum attributes
84+
85+ var enumAttr : EnumAttribute
86+ let fnAttrs : [ AttributeKind : UInt64 ] = [
87+ . alignstack: 8 ,
88+ . allocsize: 8 ,
89+ . alwaysinline: 0 ,
90+ . builtin: 0 ,
91+ . cold: 0 ,
92+ . convergent: 0 ,
93+ . inaccessiblememonly: 0 ,
94+ . inaccessiblememOrArgmemonly: 0 ,
95+ . inlinehint: 0 ,
96+ . jumptable: 0 ,
97+ . minsize: 0 ,
98+ . naked: 0 ,
99+ . noJumpTables: 0 ,
100+ . nobuiltin: 0 ,
101+ . noduplicate: 0 ,
102+ . noimplicitfloat: 0 ,
103+ . noinline: 0 ,
104+ . nonlazybind: 0 ,
105+ . noredzone: 0 ,
106+ . noreturn: 0 ,
107+ . norecurse: 0 ,
108+ . nounwind: 0 ,
109+ . optnone: 0 ,
110+ . optsize: 0 ,
111+ . readnone: 0 ,
112+ . readonly: 0 ,
113+ . writeonly: 0 ,
114+ . argmemonly: 0 ,
115+ . returnsTwice: 0 ,
116+ . safestack: 0 ,
117+ . sanitizeAddress: 0 ,
118+ . sanitizeMemory: 0 ,
119+ . sanitizeThread: 0 ,
120+ . sanitizeHWAddress: 0 ,
121+ . speculatable: 0 ,
122+ . ssp: 0 ,
123+ . sspreq: 0 ,
124+ . sspstrong: 0 ,
125+ . strictfp: 0 ,
126+ . uwtable: 0 ,
127+ ]
128+
129+ for (attrKind, value) in fnAttrs {
130+ enumAttr = fn. addAttribute ( attrKind, value: value, to: . function)
131+ XCTAssertEqual ( enumAttr. value, value)
132+ XCTAssert ( fn. attributes ( at: . function) . contains { $0. asLLVM ( ) == enumAttr. asLLVM ( ) } )
133+
134+ // LLVM issue?
135+ // Removing an integer attribute seems to always fail, because
136+ // `AttributeList::removeAttribute` (Attributes.cpp:1096) attempts to add the
137+ // attribute about to be removed without preserving its value.
138+ guard value == 0 else { continue }
139+
140+ fn. removeAttribute ( enumAttr, from: . function)
141+ XCTAssertFalse ( fn. attributes ( at: . function) . contains { $0. asLLVM ( ) == enumAttr. asLLVM ( ) } )
142+
143+ enumAttr = fn. addAttribute ( attrKind, value: value, to: . function)
144+ fn. removeAttribute ( attrKind, from: . function)
145+ XCTAssertFalse ( fn. attributes ( at: . function) . contains { $0. asLLVM ( ) == enumAttr. asLLVM ( ) } )
72146 }
73147
74- #if !os(macOS)
75- static var allTests = testCase ( [
76- ( " testIRAttributes " , testIRAttributes) ,
77- ] )
78- #endif
79- }
148+ // MARK: String attributes
149+
150+ var stringAttr : StringAttribute
151+ for (name, value) in [ ( " foo " , " " ) , ( " foo " , " bar " ) ] {
152+ stringAttr = fn. addAttribute ( name, value: value, to: . function)
153+ XCTAssertEqual ( stringAttr. name, name)
154+ XCTAssertEqual ( stringAttr. value, value)
155+ XCTAssert ( fn. attributes ( at: . function) . contains { $0. asLLVM ( ) == stringAttr. asLLVM ( ) } )
156+
157+ fn. removeAttribute ( stringAttr, from: . function)
158+ XCTAssertFalse ( fn. attributes ( at: . function) . contains { $0. asLLVM ( ) == stringAttr. asLLVM ( ) } )
159+
160+ stringAttr = fn. addAttribute ( name, to: . function)
161+ fn. removeAttribute ( name, from: . function)
162+ XCTAssertFalse ( fn. attributes ( at: . function) . contains { $0. asLLVM ( ) == stringAttr. asLLVM ( ) } )
163+ }
164+ }
165+
166+ func testSetUnsetArgumentAttributes( ) {
167+ let module = Module ( name: " ARGATTR " )
168+ let builder = IRBuilder ( module: module)
169+
170+ let i8ptr = PointerType ( pointee: IntType . int8)
171+ let fn = builder. addFunction ( " fn " ,
172+ type: FunctionType ( argTypes: [ i8ptr] , returnType: i8ptr) )
80173
174+ // MARK: Enum attributes
175+
176+ var enumAttr : EnumAttribute
177+ let argAttrs : [ AttributeKind : UInt64 ] = [
178+ . zeroext: 0 ,
179+ . signext: 0 ,
180+ . inreg: 0 ,
181+ . byval: 0 ,
182+ . inalloca: 0 ,
183+ . sret: 0 ,
184+ . align: 8 ,
185+ . noalias: 0 ,
186+ . nocapture: 0 ,
187+ . nest: 0 ,
188+ . returned: 0 ,
189+ . nonnull: 0 ,
190+ . dereferenceable: 8 ,
191+ . dereferenceableOrNull: 8 ,
192+ . swiftself: 0 ,
193+ . swifterror: 0 ,
194+ ]
195+
196+ for (attrKind, value) in argAttrs {
197+ enumAttr = fn. addAttribute ( attrKind, value: value, to: . returnValue)
198+ XCTAssertEqual ( enumAttr. value, value)
199+ XCTAssert ( fn. attributes ( at: . returnValue) . contains { $0. asLLVM ( ) == enumAttr. asLLVM ( ) } )
200+
201+ // LLVM issue?
202+ guard value == 0 else { continue }
203+
204+ fn. removeAttribute ( enumAttr, from: . returnValue)
205+ XCTAssertFalse ( fn. attributes ( at: . returnValue) . contains { $0. asLLVM ( ) == enumAttr. asLLVM ( ) } )
206+
207+ enumAttr = fn. addAttribute ( attrKind, value: value, to: . returnValue)
208+ fn. removeAttribute ( attrKind, from: . returnValue)
209+ XCTAssertFalse ( fn. attributes ( at: . returnValue) . contains { $0. asLLVM ( ) == enumAttr. asLLVM ( ) } )
210+ }
211+
212+ for (attrKind, value) in argAttrs {
213+ enumAttr = fn. addAttribute ( attrKind, value: value, to: . argument( 0 ) )
214+ XCTAssertEqual ( enumAttr. value, value)
215+ XCTAssert ( fn. attributes ( at: . argument( 0 ) ) . contains { $0. asLLVM ( ) == enumAttr. asLLVM ( ) } )
216+
217+ // LLVM issue?
218+ guard value == 0 else { continue }
219+
220+ fn. removeAttribute ( enumAttr, from: . argument( 0 ) )
221+ XCTAssertFalse ( fn. attributes ( at: . argument( 0 ) ) . contains { $0. asLLVM ( ) == enumAttr. asLLVM ( ) } )
222+
223+ enumAttr = fn. addAttribute ( attrKind, value: value, to: . argument( 0 ) )
224+ fn. removeAttribute ( attrKind, from: . argument( 0 ) )
225+ XCTAssertFalse ( fn. attributes ( at: . argument( 0 ) ) . contains { $0. asLLVM ( ) == enumAttr. asLLVM ( ) } )
226+ }
227+
228+ // MARK: String attributes
229+
230+ var stringAttr : StringAttribute
231+ for (name, value) in [ ( " foo " , " " ) , ( " foo " , " bar " ) ] {
232+ stringAttr = fn. addAttribute ( name, value: value, to: . returnValue)
233+ XCTAssertEqual ( stringAttr. name, name)
234+ XCTAssertEqual ( stringAttr. value, value)
235+ XCTAssert ( fn. attributes ( at: . returnValue) . contains { $0. asLLVM ( ) == stringAttr. asLLVM ( ) } )
236+
237+ fn. removeAttribute ( stringAttr, from: . returnValue)
238+ XCTAssertFalse ( fn. attributes ( at: . returnValue) . contains { $0. asLLVM ( ) == stringAttr. asLLVM ( ) } )
239+
240+ stringAttr = fn. addAttribute ( name, to: . returnValue)
241+ fn. removeAttribute ( name, from: . returnValue)
242+ XCTAssertFalse ( fn. attributes ( at: . returnValue) . contains { $0. asLLVM ( ) == stringAttr. asLLVM ( ) } )
243+ }
244+
245+ for (name, value) in [ ( " foo " , " " ) , ( " foo " , " bar " ) ] {
246+ stringAttr = fn. addAttribute ( name, value: value, to: . argument( 0 ) )
247+ XCTAssertEqual ( stringAttr. name, name)
248+ XCTAssertEqual ( stringAttr. value, value)
249+ XCTAssert ( fn. attributes ( at: . argument( 0 ) ) . contains { $0. asLLVM ( ) == stringAttr. asLLVM ( ) } )
250+
251+ fn. removeAttribute ( stringAttr, from: . argument( 0 ) )
252+ XCTAssertFalse ( fn. attributes ( at: . argument( 0 ) ) . contains { $0. asLLVM ( ) == stringAttr. asLLVM ( ) } )
253+
254+ stringAttr = fn. addAttribute ( name, to: . argument( 0 ) )
255+ fn. removeAttribute ( name, from: . argument( 0 ) )
256+ XCTAssertFalse ( fn. attributes ( at: . argument( 0 ) ) . contains { $0. asLLVM ( ) == stringAttr. asLLVM ( ) } )
257+ }
258+ }
259+
260+ #if !os(macOS)
261+ static var allTests = testCase ( [
262+ ( " testIRAttributes " , testIRAttributes) ,
263+ ( " testSetUnsetFunctionAttributes " , testSetUnsetFunctionAttributes) ,
264+ ( " testSetUnsetArgumentAttributes " , testSetUnsetArgumentAttributes) ,
265+ ] )
266+ #endif
267+ }
0 commit comments