@@ -6,7 +6,7 @@ import Foundation
66class IRMetadataSpec : XCTestCase {
77 func testGlobalMetadata( ) {
88 XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " IRGLOBALMETADATA " ] ) {
9- // IRGLOBALMETADATA: ; ModuleID = '[[ModuleName:IRGLOBALMETADATATest]]'
9+ // IRGLOBALMETADATA: ModuleID = '[[ModuleName:IRGLOBALMETADATATest]]'
1010 // IRGLOBALMETADATA-NEXT: source_filename = "[[ModuleName]]"
1111 let module = Module ( name: " IRGLOBALMETADATATest " )
1212 let builder = IRBuilder ( module: module)
@@ -27,7 +27,7 @@ class IRMetadataSpec : XCTestCase {
2727
2828 func testInstructionMetadata( ) {
2929 XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " IRINSTRMETADATA " ] ) {
30- // IRINSTRMETADATA: ; ModuleID = '[[ModuleName:IRINSTRMETADATATest]]'
30+ // IRINSTRMETADATA: ModuleID = '[[ModuleName:IRINSTRMETADATATest]]'
3131 // IRINSTRMETADATA-NEXT: source_filename = "[[ModuleName]]"
3232 let module = Module ( name: " IRINSTRMETADATATest " )
3333 let builder = IRBuilder ( module: module)
@@ -56,7 +56,7 @@ class IRMetadataSpec : XCTestCase {
5656
5757 func testFPMathTag( ) {
5858 XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " IRFPMATHMETADATA " ] ) {
59- // IRFPMATHMETADATA: ; ModuleID = '[[ModuleName:IRFPMathTest]]'
59+ // IRFPMATHMETADATA: ModuleID = '[[ModuleName:IRFPMathTest]]'
6060 // IRFPMATHMETADATA-NEXT: source_filename = "[[ModuleName]]"
6161 let module = Module ( name: " IRFPMathTest " )
6262 let builder = IRBuilder ( module: module)
@@ -85,7 +85,7 @@ class IRMetadataSpec : XCTestCase {
8585
8686 func testBranchWeights( ) {
8787 XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " IRBWMETADATA " ] ) {
88- // IRBWMETADATA: ; ModuleID = '[[ModuleName:IRBWMetadataTest]]'
88+ // IRBWMETADATA: ModuleID = '[[ModuleName:IRBWMetadataTest]]'
8989 // IRBWMETADATA-NEXT: source_filename = "[[ModuleName]]"
9090 let module = Module ( name: " IRBWMetadataTest " )
9191 let builder = IRBuilder ( module: module)
@@ -140,11 +140,161 @@ class IRMetadataSpec : XCTestCase {
140140 } )
141141 }
142142
143+ func testSimpleTBAA( ) {
144+ XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " IRSIMPLETBAA " ] ) {
145+ // IRSIMPLETBAA: ModuleID = '[[ModuleName:IRTBAATest]]'
146+ // IRSIMPLETBAA-NEXT: source_filename = "[[ModuleName]]"
147+ let module = Module ( name: " IRTBAATest " )
148+ let builder = IRBuilder ( module: module)
149+ let MDB = MDBuilder ( )
150+
151+ // IRSIMPLETBAA: define void @main() {
152+ let F = module. addFunction ( " main " , type: FunctionType ( argTypes: [ ] , returnType: VoidType ( ) ) )
153+ // IRSIMPLETBAA-NEXT: entry:
154+ let bb = F . appendBasicBlock ( named: " entry " )
155+ builder. positionAtEnd ( of: bb)
156+ // typedef struct {
157+ // int16_t s;
158+ // } A;
159+ let structTyA = StructType ( elementTypes: [
160+ IntType . int16
161+ ] )
162+ // typedef struct {
163+ // uint32_t s;
164+ // A a;
165+ // } B;
166+ let structTyB = StructType ( elementTypes: [
167+ IntType . int32,
168+ structTyA,
169+ ] )
170+
171+ // struct B *val = alloca(sizeof(struct B));
172+ // IRSIMPLETBAA-NEXT: %0 = alloca { i32, { i16 } }
173+ let alloca = builder. buildAlloca ( type: structTyB)
174+ // IRSIMPLETBAA-NEXT: %1 = getelementptr inbounds { i32, { i16 } }, { i32, { i16 } }* %0, i64 0, i32 1, i32 0
175+ let field = builder. buildInBoundsGEP ( alloca, indices: [
176+ IntType . int64. constant ( 0 ) , // (*this)
177+ IntType . int32. constant ( 1 ) , // .a
178+ IntType . int32. constant ( 0 ) , // .s
179+ ] )
180+ // B->a.s = 42
181+ // IRSIMPLETBAA-NEXT: store i16 42, i16* %1, !tbaa [[AccessTag:![0-9]+]]
182+ let si = builder. buildStore ( IntType . int16. constant ( 42 ) , to: field)
183+ // IRSIMPLETBAA-NEXT: ret void
184+ builder. buildRetVoid ( )
185+ // IRSIMPLETBAA-NEXT: }
186+
187+ // IRSIMPLETBAA: [[AccessTag]] = !{[[BTypeNode:![0-9]+]], [[Int16Node:![0-9]+]], i64 4, i64 4}
188+ // IRSIMPLETBAA-NEXT: [[BTypeNode]] = !{[[OmnipotentChar:![0-9]+]], i64 8, !"B", [[Int32Node:![0-9]+]], i64 0, i64 4, [[ATypeNode:![0-9]+]], i64 4, i64 2}
189+ // IRSIMPLETBAA-NEXT: [[OmnipotentChar]] = !{[[RootNode:![0-9]+]], i64 1, !"omnipotent char"}
190+ // IRSIMPLETBAA-NEXT: [[RootNode]] = !{!"TBAA Test Root"}
191+ // IRSIMPLETBAA-NEXT: [[Int32Node]] = !{[[OmnipotentChar]], i64 4, !"int32_t"}
192+ // IRSIMPLETBAA-NEXT: [[ATypeNode]] = !{[[OmnipotentChar]], i64 2, !"A", [[Int16Node]], i64 0, i64 2}
193+ // IRSIMPLETBAA-NEXT: [[Int16Node]] = !{[[OmnipotentChar]], i64 2, !"int16_t"}
194+ let rootMD = MDB . buildTBAARoot ( " TBAA Test Root " )
195+ let charMD = MDB . buildTBAATypeNode ( MDString ( " omnipotent char " ) , parent: rootMD, size: . one)
196+ let int16MD = MDB . buildTBAATypeNode ( MDString ( " int16_t " ) , parent: charMD, size: Size ( bits: 16 ) )
197+ let int32MD = MDB . buildTBAATypeNode ( MDString ( " int32_t " ) , parent: charMD, size: Size ( bits: 32 ) )
198+ let structAMD = MDB . buildTBAATypeNode ( MDString ( " A " ) ,
199+ parent: charMD,
200+ size: module. dataLayout. storeSize ( of: structTyA) ,
201+ fields: [
202+ . init( offset: . zero, size: Size ( bits: 16 ) , type: int16MD)
203+ ] )
204+ let structBMD = MDB . buildTBAATypeNode ( MDString ( " B " ) ,
205+ parent: charMD,
206+ size: module. dataLayout. storeSize ( of: structTyB) ,
207+ fields: [
208+ . init( offset: . zero, size: Size ( bits: 32 ) , type: int32MD) ,
209+ . init( offset: Size ( bits: 32 ) , size: module. dataLayout. storeSize ( of: structTyA) , type: structAMD) ,
210+ ] )
211+ let accessTag = MDB . buildTBAAAccessTag ( baseType: structBMD, accessType: int16MD, offset: Size ( bits: 32 ) , size: Size ( bits: 32 ) )
212+ si. addMetadata ( accessTag, kind: . tbaa)
213+
214+ module. dump ( )
215+ try ! module. verify ( )
216+ } )
217+ }
218+
219+ func testMemoryTransferTBAA( ) {
220+ XCTAssert ( fileCheckOutput ( of: . stderr, withPrefixes: [ " IRMEMTRANSFERTBAA " ] ) {
221+ // IRMEMTRANSFERTBAA: ModuleID = '[[ModuleName:IRTBAATest]]'
222+ // IRMEMTRANSFERTBAA-NEXT: source_filename = "[[ModuleName]]"
223+ let module = Module ( name: " IRTBAATest " )
224+ let builder = IRBuilder ( module: module)
225+ let MDB = MDBuilder ( )
226+
227+ // IRMEMTRANSFERTBAA: define void @main(i8*) {
228+ let F = module. addFunction ( " main " , type: FunctionType ( argTypes: [ PointerType . toVoid] , returnType: VoidType ( ) ) )
229+ // IRMEMTRANSFERTBAA-NEXT: entry:
230+ let bb = F . appendBasicBlock ( named: " entry " )
231+ builder. positionAtEnd ( of: bb)
232+ // typedef struct {
233+ // int16_t s;
234+ // } A;
235+ let structTyA = StructType ( elementTypes: [
236+ IntType . int16
237+ ] , isPacked: true )
238+ // typedef struct {
239+ // bool s;
240+ // // Invisible padding
241+ // unsigned pad:15;
242+ // A a;
243+ // } B;
244+ let structTyB = StructType ( elementTypes: [
245+ IntType . int1,
246+ IntType ( width: 15 ) ,
247+ structTyA,
248+ ] , isPacked: true )
249+
250+ // struct B *val = alloca(sizeof(struct B));
251+ // IRMEMTRANSFERTBAA-NEXT: %1 = alloca <{ i1, i15, <{ i16 }> }>
252+ let alloca = builder. buildAlloca ( type: structTyB)
253+ // IRMEMTRANSFERTBAA-NEXT: %2 = bitcast <{ i1, i15, <{ i16 }> }>* %1 to i8*
254+ let src = builder. buildPointerCast ( of: alloca, to: PointerType ( pointee: structTyB) )
255+ // IRMEMTRANSFERTBAA-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %0, i8* align 1 %2, i32 5, i1 false), !tbaa.struct [[StructAccssTag:![0-9]+]]
256+ let inst = builder. buildMemCpy ( to: F . parameters [ 0 ] , module. dataLayout. abiAlignment ( of: structTyB) ,
257+ from: src, module. dataLayout. abiAlignment ( of: structTyB) ,
258+ length: IntType . int32. constant ( module. dataLayout. abiSize ( of: structTyB) . rawValue) )
259+
260+ // IRMEMTRANSFERTBAA-NEXT: ret void
261+ builder. buildRetVoid ( )
262+ // IRMEMTRANSFERTBAA-NEXT: }
263+
264+ // IRMEMTRANSFERTBAA: [[StructAccssTag]] = !{i64 0, i64 1, [[Field1AccessTag:![0-9]+]], i64 2, i64 2, [[Field2AccessTag:![0-9]+]]}
265+ // IRMEMTRANSFERTBAA-NEXT: [[Field1AccessTag]] = !{[[BoolTypeTag:![0-9]+]], [[BoolTypeTag]], i64 0, i64 4}
266+ // IRMEMTRANSFERTBAA-NEXT: [[BoolTypeTag]] = !{[[OmnipotentCharTypeTag:![0-9]+]], i64 1, !"bool"}
267+ // IRMEMTRANSFERTBAA-NEXT: [[OmnipotentCharTypeTag]] = !{[[TBAARoot:![0-9]+]], i64 1, !"omnipotent char"}
268+ // IRMEMTRANSFERTBAA-NEXT: [[TBAARoot]] = !{!"TBAA Test Root"}
269+ // IRMEMTRANSFERTBAA-NEXT: [[Field2AccessTag]] = !{[[Int16TypeTag:![0-9]+]], [[Int16TypeTag]], i64 4, i64 2}
270+ // IRMEMTRANSFERTBAA-NEXT: [[Int16TypeTag]] = !{[[OmnipotentCharTypeTag]], i64 2, !"int16_t"}
271+
272+ // TBAA Types
273+ let rootMD = MDB . buildTBAARoot ( " TBAA Test Root " )
274+ let charMD = MDB . buildTBAATypeNode ( MDString ( " omnipotent char " ) , parent: rootMD, size: . one)
275+ let int16MD = MDB . buildTBAATypeNode ( MDString ( " int16_t " ) , parent: charMD, size: Size ( bits: 16 ) )
276+ let boolMD = MDB . buildTBAATypeNode ( MDString ( " bool " ) , parent: charMD, size: Size ( bits: 1 ) )
277+
278+ // Member accesses
279+ let field1Access = MDB . buildTBAAAccessTag ( baseType: boolMD, accessType: boolMD, offset: . zero, size: Size ( bits: 32 ) )
280+ let field2Access = MDB . buildTBAAAccessTag ( baseType: int16MD, accessType: int16MD, offset: Size ( bits: 32 ) , size: Size ( bits: 16 ) )
281+ let structMD = MDB . buildTBAAStructNode ( [
282+ . init( offset: . zero, size: Size ( bits: 8 ) , type: field1Access) ,
283+ . init( offset: Size ( bits: 16 ) , size: Size ( bits: 16 ) , type: field2Access) ,
284+ ] )
285+ inst. addMetadata ( structMD, kind: . tbaaStruct)
286+
287+ module. dump ( )
288+ try ! module. verify ( )
289+ } )
290+ }
291+
143292 #if !os(macOS)
144293 static var allTests = testCase ( [
145294 ( " testGlobalMetadata " , testGlobalMetadata) ,
146295 ( " testFPMathTag " , testFPMathTag) ,
147296 ( " testBranchWeights " , testBranchWeights) ,
297+ ( " testSimpleTBAA " , testSimpleTBAA) ,
148298 ] )
149299 #endif
150300}
0 commit comments