Skip to content

Commit 7ed55bc

Browse files
committed
Cut out the non-struct-path TBAA accessors
These no longer pass validation in LLVM
1 parent 23505a4 commit 7ed55bc

File tree

1 file changed

+153
-88
lines changed

1 file changed

+153
-88
lines changed

Sources/LLVM/MDBuilder.swift

Lines changed: 153 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -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

224236
extension 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

Comments
 (0)