@@ -219,56 +219,78 @@ public struct TBAAStructField {
219219 public let size : Size
220220 /// The type metadata node for this struct field.
221221 public let type : MDNode
222+
223+ /// Create a new TBAA struct field.
224+ ///
225+ /// - Parameters:
226+ /// - The offsset of this field relative to its parent in bytes.
227+ /// - The size of this field in bytes.
228+ /// - TBAA type metadata for the field.
229+ public init ( offset: Size , size: Size , type: MDNode ) {
230+ self . offset = offset
231+ self . size = size
232+ self . type = type
233+ }
222234}
223235
224236extension MDBuilder {
225- public func buildAARoot( _ name: String , _ extra: MDNode ? = nil ) -> MDNode {
226- // To ensure uniqueness the root node is self-referential.
227- let dummy = TemporaryMDNode ( in: self . context, operands: [ ] )
228- var ops = [ IRMetadata] ( )
229- if let extra = extra {
230- ops. append ( extra)
231- }
232- if !name. isEmpty {
233- ops. append ( MDString ( name) )
237+ /// Build a metadata node for the root of a TBAA hierarchy with the given name.
238+ ///
239+ /// - Parameters:
240+ /// - name: The name of the TBAA root node.
241+ /// - Returns: A metadata node representing a TBAA hierarchy root.
242+ public func buildTBAARoot( _ name: String = " " ) -> MDNode {
243+ guard !name. isEmpty else {
244+ return self . buildAnonymousAARoot ( )
234245 }
235- let root = MDNode ( in: self . context, operands: ops)
236- // At this point we have
237- // !0 = metadata !{} <- dummy
238- // !1 = metadata !{metadata !0} <- root
239- // Replace the dummy operand with the root node itself and delete the dummy.
240- dummy. replaceAllUses ( with: root)
241- // We now have
242- // !1 = metadata !{metadata !1} <- self-referential root
243- return root
244- }
245-
246- public func buildTBAARoot( _ name: String ) -> MDNode {
247246 return MDNode ( in: self . context, operands: [ MDString ( name) ] )
248247 }
249248
250- public func buildTBAANode( _ name: String , parent: MDNode , isConstant: Bool ) -> MDNode {
251- if isConstant {
252- let flags = IntType ( width: 64 , in: self . context) . constant ( 1 )
253- return MDNode ( in: self . context, operands: [
254- MDString ( name) ,
255- parent,
256- MDNode ( constant: flags)
257- ] )
258- }
259- return MDNode ( in: self . context, operands: [
260- MDString ( name) ,
261- parent
262- ] )
263- }
264-
265- public func buildAliasScopeDomain( _ name: String , _ domain: MDNode ? = nil ) -> MDNode {
266- if let domain = domain {
267- return MDNode ( in: self . context, operands: [ MDString ( name) , domain ] )
249+ /// Build a metadata node suitable for an `alias.scope` metadata attachment.
250+ ///
251+ /// When evaluating an aliasing query, if for some domain, the set of scopes
252+ /// with that domain in one instruction’s alias.scope list is a subset of (or
253+ /// equal to) the set of scopes for that domain in another instruction’s
254+ /// noalias list, then the two memory accesses are assumed not to alias.
255+ ///
256+ /// Because scopes in one domain don’t affect scopes in other domains,
257+ /// separate domains can be used to compose multiple independent noalias
258+ /// sets. This is used for example during inlining. As the noalias function
259+ /// parameters are turned into noalias scope metadata, a new domain is used
260+ /// every time the function is inlined.
261+ ///
262+ /// - Parameters:
263+ /// - name: The name of the alias scope domain.
264+ /// - domain: The domain of the alias scope, if any.
265+ /// - Returns: A metadata node representing a TBAA alias scope.
266+ public func buildAliasScopeDomain( _ name: String = " " , _ domain: MDNode ? = nil ) -> MDNode {
267+ if name. isEmpty {
268+ if let domain = domain {
269+ return self . buildAnonymousAARoot ( name, domain)
270+ }
271+ return self . buildAnonymousAARoot ( name)
272+ } else {
273+ if let domain = domain {
274+ return MDNode ( in: self . context, operands: [ MDString ( name) , domain ] )
275+ }
276+ return MDNode ( in: self . context, operands: [ MDString ( name) ] )
268277 }
269- return MDNode ( in: self . context, operands: [ MDString ( name) ] )
270278 }
271279
280+ /// Builds a metadata node suitable for a `tbaa.struct` metadata attachment.
281+ ///
282+ /// `tbaa.struct` metadata can describe which memory subregions in a
283+ /// `memcpy` are padding and what the TBAA tags of the struct are.
284+ ///
285+ /// Note that the fields need not be contiguous. In the following example,
286+ /// there is a 4 byte gap between the two fields. This gap represents padding
287+ /// which does not carry useful data and need not be preserved.
288+ ///
289+ /// !4 = !{ i64 0, i64 4, !1, i64 8, i64 4, !2 }
290+ ///
291+ /// - Parameters:
292+ /// - fields: The fields of the struct.
293+ /// - Returns: A metadata node representing a TBAA struct descriptor.
272294 public func buildTBAAStructNode( _ fields: [ TBAAStructField ] ) -> MDNode {
273295 var ops = [ IRMetadata] ( )
274296 ops. reserveCapacity ( fields. count * 3 )
@@ -281,46 +303,28 @@ extension MDBuilder {
281303 return MDNode ( in: self . context, operands: ops)
282304 }
283305
284- public func buildTBAAStructTypeName( _ name: String , fields: [ ( MDNode , Size ) ] ) -> MDNode {
285- var ops = [ IRMetadata] ( )
286- ops. reserveCapacity ( fields. count * 2 + 1 )
287- let int64 = IntType ( width: 64 , in: self . context)
288- ops. append ( MDString ( name) )
289- for (type, offset) in fields {
290- ops. append ( type)
291- ops. append ( MDNode ( constant: int64. constant ( offset. rawValue) ) )
292- }
293- return MDNode ( in: self . context, operands: ops)
294- }
295-
296- public func buildTBAAScalarTypeNode( _ name: String , _ parent: MDNode , _ offset: Size ) -> MDNode {
297- let off = IntType ( width: 64 , in: self . context) . constant ( offset. rawValue)
298- return MDNode ( in: self . context, operands: [
299- MDString ( name) ,
300- parent,
301- MDNode ( constant: off)
302- ] )
303- }
304-
305- public func buildTBAAStructTagNode( _ baseType: MDNode , _ accessType: MDNode , _ offset: Size , _ isConstant: Bool ) -> MDNode {
306- let int64 = IntType ( width: 64 , in: self . context)
307- let off = int64. constant ( offset. rawValue)
308- if isConstant {
309- return MDNode ( in: self . context, operands: [
310- baseType,
311- accessType,
312- MDNode ( constant: off) ,
313- MDNode ( constant: int64. constant ( 1 ) )
314- ] )
315- }
316- return MDNode ( in: self . context, operands: [
317- baseType,
318- accessType,
319- MDNode ( constant: off) ,
320- ] )
321- }
322-
323- public func buildTBAATypeNode( _ parent: MDNode , _ size: Size , _ id: IRMetadata , _ fields: [ TBAAStructField ] ) -> MDNode {
306+ /// Builds a TBAA Type Descriptor.
307+ ///
308+ /// Type descriptors describe the type system of the higher level language
309+ /// being compiled. Scalar type descriptors describe types that do not
310+ /// contain other types. Each scalar type has a parent type, which must also
311+ /// be a scalar type or the TBAA root. Via this parent relation, scalar types
312+ /// within a TBAA root form a tree. Struct type descriptors denote types that
313+ /// contain a sequence of other type descriptors, at known offsets. These
314+ /// contained type descriptors can either be struct type descriptors
315+ /// themselves or scalar type descriptors.
316+ ///
317+ /// - Parameters:
318+ /// - parent: The parent type node of this type node or the TBAA root node
319+ /// if it is a top-level entity.
320+ /// - size: The size of the type in bytes.
321+ /// - id: The metadata node whose identity uniquely identifies this node as
322+ /// well. These are often `MDString` values.
323+ /// - fields: The fields of the type, if any.
324+ /// - Returns: A metadata node representing a TBAA type descriptor.
325+ public func buildTBAATypeNode(
326+ _ id: IRMetadata , parent: MDNode , size: Size , fields: [ TBAAStructField ] = [ ]
327+ ) -> MDNode {
324328 var ops = [ IRMetadata] ( )
325329 ops. reserveCapacity ( 3 + fields. count * 3 )
326330 let int64 = IntType ( width: 64 , in: self . context)
@@ -335,26 +339,87 @@ extension MDBuilder {
335339 return MDNode ( in: self . context, operands: ops)
336340 }
337341
338- public func buildTBAAAccessTag( _ baseType: MDNode , _ accessType: MDNode , _ offset: Size , _ size: Size , _ isImmutable: Bool ) -> MDNode {
342+ /// Builds a TBAA Access Tag.
343+ ///
344+ /// Access tags are metadata nodes attached to `load` and `store`
345+ /// instructions. Access tags use type descriptors to describe the
346+ /// location being accessed in terms of the type system of the higher
347+ /// level language. Access tags are tuples consisting of a base type,
348+ /// an access type and an offset. The base type is a scalar type
349+ /// descriptor or a struct type descriptor, the access type is a
350+ /// scalar type descriptor, and the offset is a constant integer.
351+ ///
352+ /// Tag Structure
353+ /// =============
354+ ///
355+ /// The access tag `(BaseTy, AccessTy, Offset)` can describe one of two
356+ /// things:
357+ ///
358+ /// - If `BaseTy` is a struct type, the tag describes a memory access
359+ /// (`load` or `store`) of a value of type `AccessTy` contained in
360+ /// the struct type `BaseTy` at offset `Offset`.
361+ /// - If `BaseTy` is a scalar type, `Offset` must be 0 and `BaseTy` and
362+ /// `AccessTy` must be the same; and the access tag describes a scalar
363+ /// access with scalar type `AccessTy`.
364+ ///
365+ /// - Parameters:
366+ /// - baseType: The base type of the access. This is the structure or
367+ /// scalar type that corresponds to the type of the source value in a
368+ /// `load` instruction, or the type of the destination value in a `store`
369+ /// instruction.
370+ /// - accessType: The type of the accessed value. This is the type that
371+ /// corresponds to the type of the destination value in a `load`
372+ /// instruction, or the type of the source value in a `store` instruction.
373+ /// - offset: The ofset of the memory accesss into the base type. If the
374+ /// base type is scalar, this value must be 0.
375+ /// - size: The size of the access in bytes.
376+ /// - immutable: If true, accesses to this memory are never writes.
377+ /// This corresponds to the `const` memory qualifier in C and C++.
378+ /// - Returns: A metadata node representing a TBAA accesss tag.
379+ public func buildTBAAAccessTag(
380+ baseType: MDNode , accessType: MDNode ,
381+ offset: Size , size: Size , immutable: Bool = false
382+ ) -> MDNode {
339383 let int64 = IntType ( width: 64 , in: self . context)
340- let off = MDNode ( constant: int64. constant ( offset. rawValue) )
341- let siz = MDNode ( constant: int64. constant ( size. rawValue) )
342- if isImmutable {
384+ let offNode = MDNode ( constant: int64. constant ( offset. rawValue) )
385+ let sizeNode = MDNode ( constant: int64. constant ( size. rawValue) )
386+ if immutable {
343387 return MDNode ( in: self . context, operands: [
344388 baseType,
345389 accessType,
346- off ,
347- siz ,
390+ offNode ,
391+ sizeNode ,
348392 MDNode ( constant: int64. constant ( 1 ) ) ,
349393 ] )
350394 }
351395 return MDNode ( in: self . context, operands: [
352396 baseType,
353397 accessType,
354- off ,
355- siz ,
398+ offNode ,
399+ sizeNode ,
356400 ] )
357401 }
402+
403+ private func buildAnonymousAARoot( _ name: String = " " , _ extra: MDNode ? = nil ) -> MDNode {
404+ // To ensure uniqueness the root node is self-referential.
405+ let dummy = TemporaryMDNode ( in: self . context, operands: [ ] )
406+ var ops = [ IRMetadata] ( )
407+ if let extra = extra {
408+ ops. append ( extra)
409+ }
410+ if !name. isEmpty {
411+ ops. append ( MDString ( name) )
412+ }
413+ let root = MDNode ( in: self . context, operands: ops)
414+ // At this point we have
415+ // !0 = metadata !{} <- dummy
416+ // !1 = metadata !{metadata !0} <- root
417+ // Replace the dummy operand with the root node itself and delete the dummy.
418+ dummy. replaceAllUses ( with: root)
419+ // We now have
420+ // !1 = metadata !{metadata !1} <- self-referential root
421+ return root
422+ }
358423}
359424
360425// MARK: Irreducible Loop Metadata
0 commit comments