Skip to content

Commit e4aa37b

Browse files
authored
Merge pull request #173 from CodaFi/all-truth-no-lies
Add conveniences for building declare and value intrinsics
2 parents 34fbb5f + 2c92a2e commit e4aa37b

File tree

4 files changed

+561
-0
lines changed

4 files changed

+561
-0
lines changed

Sources/LLVM/DIBuilder.swift

+138
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,144 @@ public final class DIBuilder {
3737
}
3838
}
3939

40+
// MARK: Declarations
41+
42+
extension DIBuilder {
43+
/// Builds a call to a debug intrinsic for declaring a local variable and
44+
/// inserts it before a given instruction.
45+
///
46+
/// This intrinsic provides information about a local element
47+
/// (e.g. a variable) defined in some lexical scope. The variable does not
48+
/// have to be physically represented in the source.
49+
///
50+
/// Each variable may have at most one corresponding `llvm.dbg.declare`. A
51+
/// variable declaration is not control-dependent: A variable is declared at
52+
/// most once, and that declaration remains in effect until the lifetime of
53+
/// that variable ends.
54+
///
55+
/// `lldb.dbg.declare` can make optimizing code that needs accurate debug info
56+
/// difficult because of these scoping constraints.
57+
///
58+
/// - Parameters:
59+
/// - variable: The IRValue of a variable to declare.
60+
/// - before: The instruction before which the intrinsic will be inserted.
61+
/// - metadata: Local variable metadata.
62+
/// - expr: A "complex expression" that modifies the current
63+
/// variable declaration.
64+
/// - location: The location of the variable in source.
65+
public func buildDeclare(
66+
of variable: IRValue,
67+
before: Instruction,
68+
metadata: LocalVariableMetadata,
69+
expr: ExpressionMetadata,
70+
location: DebugLocation
71+
) {
72+
guard let _ = LLVMDIBuilderInsertDeclareBefore(
73+
self.llvm, variable.asLLVM(), metadata.asMetadata(),
74+
expr.asMetadata(), location.asMetadata(), before.asLLVM()) else {
75+
fatalError()
76+
}
77+
}
78+
79+
/// Builds a call to a debug intrinsic for declaring a local variable and
80+
/// inserts it at the end of a given basic block.
81+
///
82+
/// This intrinsic provides information about a local element
83+
/// (e.g. a variable) defined in some lexical scope. The variable does not
84+
/// have to be physically represented in the source.
85+
///
86+
/// Each variable may have at most one corresponding `llvm.dbg.declare`. A
87+
/// variable declaration is not control-dependent: A variable is declared at
88+
/// most once, and that declaration remains in effect until the lifetime of
89+
/// that variable ends.
90+
///
91+
/// `lldb.dbg.declare` can make optimizing code that needs accurate debug info
92+
/// difficult because of these scoping constraints.
93+
///
94+
/// - Parameters:
95+
/// - variable: The IRValue of a variable to declare.
96+
/// - block: The block in which the intrinsic will be placed.
97+
/// - metadata: Local variable metadata.
98+
/// - expr: A "complex expression" that modifies the current
99+
/// variable declaration.
100+
/// - location: The location of the variable in source.
101+
public func buildDeclare(
102+
of variable: IRValue,
103+
atEndOf block: BasicBlock,
104+
metadata: LocalVariableMetadata,
105+
expr: ExpressionMetadata,
106+
location: DebugLocation
107+
) {
108+
guard let _ = LLVMDIBuilderInsertDeclareAtEnd(
109+
self.llvm, variable.asLLVM(), metadata.asMetadata(),
110+
expr.asMetadata(), location.asMetadata(), block.asLLVM()) else {
111+
fatalError()
112+
}
113+
}
114+
115+
/// Builds a call to a debug intrinsic for providing information about the
116+
/// value of a local variable and inserts it before a given instruction.
117+
///
118+
/// This intrinsic provides information to model the result of a source
119+
/// variable being set to a new value.
120+
///
121+
/// This intrinsic is built to describe the value of a source variable
122+
/// *directly*. That is, the source variable may be a value or an address,
123+
/// but the value for that variable provided to this intrinsic is considered
124+
/// without interpretation to be the value of the given variable.
125+
///
126+
/// - Parameters:
127+
/// - value: The value to set the given variable to.
128+
/// - metadata: Metadata for the given local variable.
129+
/// - before: The instruction before which the intrinsic will be inserted.
130+
/// - expr: A "complex expression" that modifies the given value.
131+
/// - location: The location of the variable assignment in source.
132+
public func buildDbgValue(
133+
of value: IRValue,
134+
to metadata: LocalVariableMetadata,
135+
before: Instruction,
136+
expr: ExpressionMetadata,
137+
location: DebugLocation
138+
) {
139+
guard let _ = LLVMDIBuilderInsertDbgValueBefore(
140+
self.llvm, value.asLLVM(), metadata.asMetadata(),
141+
expr.asMetadata(), location.asMetadata(), before.asLLVM()) else {
142+
fatalError()
143+
}
144+
}
145+
146+
/// Builds a call to a debug intrinsic for providing information about the
147+
/// value of a local variable and inserts it before a given instruction.
148+
///
149+
/// This intrinsic provides information to model the result of a source
150+
/// variable being set to a new value.
151+
///
152+
/// This intrinsic is built to describe the value of a source variable
153+
/// *directly*. That is, the source variable may be a value or an address,
154+
/// but the value for that variable provided to this intrinsic is considered
155+
/// without interpretation to be the value of the given variable.
156+
///
157+
/// - Parameters:
158+
/// - value: The value to set the given variable to.
159+
/// - metadata: Metadata for the given local variable.
160+
/// - block: The block in which the intrinsic will be placed.
161+
/// - expr: A "complex expression" that modifies the given value.
162+
/// - location: The location of the variable assignment in source.
163+
public func buildDbgValue(
164+
of value: IRValue,
165+
to metadata: LocalVariableMetadata,
166+
atEndOf block: BasicBlock,
167+
expr: ExpressionMetadata,
168+
location: DebugLocation
169+
) {
170+
guard let _ = LLVMDIBuilderInsertDbgValueAtEnd(
171+
self.llvm, value.asLLVM(), metadata.asMetadata(),
172+
expr.asMetadata(), location.asMetadata(), block.asLLVM()) else {
173+
fatalError()
174+
}
175+
}
176+
}
177+
40178
// MARK: Scope Entities
41179

42180
extension DIBuilder {

Sources/LLVM/IRMetadata.swift

+4
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ extension DIType {
113113
}
114114

115115
/// A `DebugLocation` represents a location in source.
116+
///
117+
/// Debug locations are de-duplicated by file and line. If more than one
118+
/// location inside a given scope needs to share a line, a discriminator value
119+
/// must be set or those locations will be considered equivalent.
116120
public struct DebugLocation: IRMetadata {
117121
internal let llvm: LLVMMetadataRef
118122

0 commit comments

Comments
 (0)