@@ -22,6 +22,9 @@ public protocol _IRMetadataInitializerHack {
2222/// Metadata does not have a type, and is not a value. If referenced from a call
2323/// instruction, it uses the metadata type.
2424///
25+ /// Debug Information
26+ /// =================
27+ ///
2528/// The idea of LLVM debugging information is to capture how the important
2629/// pieces of the source-language’s Abstract Syntax Tree map onto LLVM code.
2730/// LLVM takes a number of positions on the impact of the broader compilation
@@ -388,6 +391,129 @@ public struct NameSpaceMetadata: DIScope {
388391 }
389392}
390393
394+ /// `MDString` nodes represent string constants in metadata nodes.
395+ public struct MDString : IRMetadata , ExpressibleByStringLiteral {
396+ public typealias StringLiteralType = String
397+
398+ private let llvm : LLVMMetadataRef
399+
400+ public init ( llvm: LLVMMetadataRef ) {
401+ self . llvm = llvm
402+ }
403+
404+ /// Create an `MDString` node from the given string value.
405+ ///
406+ /// - Parameters:
407+ /// - value: The string value to assign to this metadata node.
408+ public init ( _ value: String ) {
409+ self . llvm = LLVMValueAsMetadata ( LLVMMDString ( value, UInt32 ( value. count) ) )
410+ }
411+
412+ public init ( stringLiteral value: String ) {
413+ self . llvm = LLVMValueAsMetadata ( LLVMMDString ( value, UInt32 ( value. count) ) )
414+ }
415+
416+ public func asMetadata( ) -> LLVMMetadataRef {
417+ return llvm
418+ }
419+ }
420+
421+ /// `MDNode` objects represent generic nodes in a metadata graph.
422+ ///
423+ /// A metadata node is a tuple of references to other metadata. In general,
424+ /// metadata graphs are acyclic and terminate in metadata nodes without
425+ /// operands.
426+ public struct MDNode : IRMetadata {
427+ private let llvm : LLVMMetadataRef
428+
429+ public init ( llvm: LLVMMetadataRef ) {
430+ self . llvm = llvm
431+ }
432+
433+ /// Create a metadata node in the given context with the given operands.
434+ ///
435+ /// - Parameters:
436+ /// - context: The context to allocate the node in.
437+ /// - operands: The operands to attach to the metadata node.
438+ public init ( in context: Context = . global, operands: [ IRMetadata ] ) {
439+ var operands = operands. map { $0. asMetadata ( ) as Optional }
440+ self . llvm = operands. withUnsafeMutableBufferPointer { buf in
441+ return LLVMMDNodeInContext2 ( context. llvm, buf. baseAddress!, UInt32 ( buf. count) )
442+ }
443+ }
444+
445+ /// Create a metadata node with the value of a given constant.
446+ ///
447+ /// - Parameters:
448+ /// - constant: The constant value to attach to the node.
449+ public init ( constant: IRConstant ) {
450+ self . llvm = LLVMValueAsMetadata ( constant. asLLVM ( ) )
451+ }
452+
453+ public func asMetadata( ) -> LLVMMetadataRef {
454+ return llvm
455+ }
456+ }
457+
458+ /// Represents a temporary metadata node.
459+ ///
460+ /// Temporary metadata nodes aid in the construction of cyclic metadata. The
461+ /// typical construction pattern is usually as follows:
462+ ///
463+ /// // Allocate a temporary temp node
464+ /// let temp = TemporaryMDNode(in: context, operands: [])
465+ /// // Prepare the operands to the metadata node...
466+ /// var ops = [IRMetadata]()
467+ /// // ...
468+ /// // Create the real node
469+ /// let root = MDNode(in: context, operands: ops)
470+ ///
471+ /// At this point we have the following metadata structure:
472+ ///
473+ /// // !0 = metadata !{} <- temp
474+ /// // !1 = metadata !{metadata !0} <- root
475+ /// // Replace the temp operand with the root node
476+ ///
477+ /// The knot is tied by RAUW'ing the temporary node:
478+ ///
479+ /// temp.replaceAllUses(with: root)
480+ /// // We now have
481+ /// // !1 = metadata !{metadata !1} <- self-referential root
482+ ///
483+ /// - Warning: It is critical that temporary metadata nodes be "RAUW'd"
484+ /// (replace-all-uses-with) before the metadata graph is finalized. After
485+ /// that time, all remaining temporary metadata nodes will become unresolved
486+ /// metadata.
487+ public class TemporaryMDNode : IRMetadata {
488+ private let llvm : LLVMMetadataRef
489+
490+ required public init ( llvm: LLVMMetadataRef ) {
491+ self . llvm = llvm
492+ }
493+
494+ /// Create a new temporary metadata node in the given context with the
495+ /// given operands.
496+ ///
497+ /// - Parameters:
498+ /// - context: The context to allocate the node in.
499+ /// - operands: The operands to attach to the metadata node.
500+ public init ( in context: Context = . global, operands: [ IRMetadata ] ) {
501+ var operands = operands. map { $0. asMetadata ( ) as Optional }
502+ self . llvm = operands. withUnsafeMutableBufferPointer { buf in
503+ return LLVMTemporaryMDNode ( context. llvm, buf. baseAddress!, buf. count)
504+ }
505+ }
506+
507+ /// Deinitialize this value and dispose of its resources.
508+ deinit {
509+ LLVMDisposeTemporaryMDNode ( self . llvm)
510+ }
511+
512+ public func asMetadata( ) -> LLVMMetadataRef {
513+ return llvm
514+ }
515+ }
516+
391517/// `ExpressionMetadata` nodes represent expressions that are inspired by the
392518/// DWARF expression language. They are used in debug intrinsics (such as
393519/// llvm.dbg.declare and llvm.dbg.value) to describe how the referenced LLVM
0 commit comments