Skip to content

Commit 880fbbe

Browse files
committed
Test set/unset attributes
1 parent b35f5bc commit 880fbbe

File tree

1 file changed

+258
-71
lines changed

1 file changed

+258
-71
lines changed

Tests/LLVMTests/IRAttributesSpec.swift

Lines changed: 258 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,77 +4,264 @@ import FileCheck
44
import Foundation
55

66
class 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

Comments
 (0)