Skip to content

Commit 90d8858

Browse files
authored
Merge pull request #162 from CodaFi/dwarf-fortress
Complete Debug Information
2 parents 89e573a + 9b68053 commit 90d8858

8 files changed

+1861
-186
lines changed

Sources/LLVM/DIBuilder.swift

Lines changed: 973 additions & 175 deletions
Large diffs are not rendered by default.

Sources/LLVM/Function.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ public class Function: IRGlobal {
1111
self.llvm = llvm
1212
}
1313

14+
/// Accesses the metadata associated with this function.
15+
///
16+
/// To build new function metadata, see `DIBuilder.buildFunction`.
17+
public var metadata: FunctionMetadata {
18+
get { return FunctionMetadata(llvm: LLVMGetSubprogram(self.llvm)) }
19+
set { LLVMSetSubprogram(self.llvm, newValue.asMetadata()) }
20+
}
21+
1422
/// Accesses the calling convention for this function.
1523
public var callingConvention: CallingConvention {
1624
get { return CallingConvention(llvm: LLVMCallConv(rawValue: LLVMGetFunctionCallConv(llvm))) }

Sources/LLVM/IRBuilder.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ extension IRBuilder {
8484
}
8585
}
8686

87+
// MARK: Debug Information
88+
89+
extension IRBuilder {
90+
/// Access location information used by debugging information.
91+
public var currentDebugLocation: DebugLocation {
92+
get { return DebugLocation(llvm: LLVMValueAsMetadata(LLVMGetCurrentDebugLocation(self.llvm))) }
93+
set { LLVMSetCurrentDebugLocation(self.llvm, LLVMMetadataAsValue(self.module.context.llvm, newValue.asMetadata())) }
94+
}
95+
}
96+
8797
// MARK: Convenience Instructions
8898

8999
extension IRBuilder {

Sources/LLVM/Metadata.swift

Lines changed: 273 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,134 @@
22
import cllvm
33
#endif
44

5-
public protocol Metadata {
5+
public protocol _IRMetadataInitializerHack {
6+
init(llvm: LLVMMetadataRef)
7+
}
8+
9+
/// The `Metadata` protocol captures those types that represent metadata nodes
10+
/// in LLVM IR.
11+
///
12+
/// LLVM IR allows metadata to be attached to instructions in the program that
13+
/// can convey extra information about the code to the optimizers and code
14+
/// generator. One example application of metadata is source-level debug
15+
/// information.
16+
///
17+
/// Metadata does not have a type, and is not a value. If referenced from a call
18+
/// instruction, it uses the metadata type.
19+
///
20+
/// The idea of LLVM debugging information is to capture how the important
21+
/// pieces of the source-language’s Abstract Syntax Tree map onto LLVM code.
22+
/// LLVM takes a number of positions on the impact of the broader compilation
23+
/// process on debug information:
24+
///
25+
/// - Debugging information should have very little impact on the rest of the
26+
/// compiler. No transformations, analyses, or code generators should need to
27+
/// be modified because of debugging information.
28+
/// - LLVM optimizations should interact in well-defined and easily described
29+
/// ways with the debugging information.
30+
/// - Because LLVM is designed to support arbitrary programming languages,
31+
/// LLVM-to-LLVM tools should not need to know anything about the semantics
32+
/// of the source-level-language.
33+
/// - Source-level languages are often widely different from one another. LLVM
34+
/// should not put any restrictions of the flavor of the source-language, and
35+
/// the debugging information should work with any language.
36+
/// - With code generator support, it should be possible to use an LLVM compiler
37+
/// to compile a program to native machine code and standard debugging
38+
/// formats. This allows compatibility with traditional machine-code level
39+
/// debuggers, like GDB, DBX, or CodeView.
40+
public protocol Metadata: _IRMetadataInitializerHack {
641
func asMetadata() -> LLVMMetadataRef
742
}
843

44+
extension Metadata {
45+
/// Replaces all uses of the this metadata with the given metadata.
46+
///
47+
/// - parameter metadata: The new value to swap in.
48+
public func replaceAllUses(with metadata: Metadata) {
49+
LLVMMetadataReplaceAllUsesWith(self.asMetadata(), metadata.asMetadata())
50+
}
51+
}
52+
53+
extension Metadata {
54+
/// Dumps a representation of this metadata to stderr.
55+
public func dump() {
56+
LLVMDumpValue(LLVMMetadataAsValue(LLVMGetGlobalContext(), self.asMetadata()))
57+
}
58+
59+
public func forceCast<DestTy: Metadata>(to: DestTy.Type) -> DestTy {
60+
return DestTy(llvm: self.asMetadata())
61+
}
62+
}
63+
64+
/// Denotes a scope in which child metadata nodes can be inserted.
65+
public protocol DIScope: Metadata {}
66+
67+
/// Denotes metadata for a type.
68+
public protocol DIType: DIScope {}
69+
70+
extension DIType {
71+
/// Retrieves the name of this type.
72+
public var name: String {
73+
var length: Int = 0
74+
let cstring = LLVMDITypeGetName(self.asMetadata(), &length)
75+
return String(cString: cstring!)
76+
}
77+
78+
/// Retrieves the size of the type represented by this metadata in bits.
79+
public var sizeInBits: Size {
80+
return Size(LLVMDITypeGetSizeInBits(self.asMetadata()))
81+
}
82+
83+
/// Retrieves the offset of the type represented by this metadata in bits.
84+
public var offsetInBits: Size {
85+
return Size(LLVMDITypeGetOffsetInBits(self.asMetadata()))
86+
}
87+
88+
/// Retrieves the alignment of the type represented by this metadata in bits.
89+
public var alignmentInBits: Alignment {
90+
return Alignment(LLVMDITypeGetAlignInBits(self.asMetadata()))
91+
}
92+
93+
/// Retrieves the line the type represented by this metadata is declared on.
94+
public var line: Int {
95+
return Int(LLVMDITypeGetLine(self.asMetadata()))
96+
}
97+
98+
/// Retrieves the flags the type represented by this metadata is declared
99+
/// with.
100+
public var flags: DIFlags {
101+
return DIFlags(rawValue: LLVMDITypeGetFlags(self.asMetadata()).rawValue)
102+
}
103+
}
104+
105+
/// A `DebugLocation` represents a location in source.
106+
public struct DebugLocation: Metadata {
107+
internal let llvm: LLVMMetadataRef
108+
109+
public func asMetadata() -> LLVMMetadataRef {
110+
return llvm
111+
}
112+
113+
/// Retrieves the line described by this location.
114+
public var line: Int {
115+
return Int(LLVMDILocationGetLine(self.llvm))
116+
}
117+
118+
/// Retrieves the column described by this location.
119+
public var column: Int {
120+
return Int(LLVMDILocationGetColumn(self.llvm))
121+
}
122+
123+
/// Retrieves the enclosing scope containing this location.
124+
public var scope: DIScope {
125+
return DIOpaqueType(llvm: LLVMDILocationGetScope(self.llvm))
126+
}
127+
128+
public init(llvm: LLVMMetadataRef) {
129+
self.llvm = llvm
130+
}
131+
}
132+
9133
struct AnyMetadata: Metadata {
10134
let llvm: LLVMMetadataRef
11135

@@ -14,59 +138,200 @@ struct AnyMetadata: Metadata {
14138
}
15139
}
16140

17-
public struct VariableMetadata: Metadata {
141+
struct DIOpaqueType: DIType {
142+
internal let llvm: LLVMMetadataRef
143+
144+
public func asMetadata() -> LLVMMetadataRef {
145+
return llvm
146+
}
147+
148+
public init(llvm: LLVMMetadataRef) {
149+
self.llvm = llvm
150+
}
151+
}
152+
153+
/// `CompileUnitMetadata` nodes represent a compile unit, the root of a metadata
154+
/// hierarchy for a translation unit.
155+
///
156+
/// Compile unit descriptors provide the root scope for objects declared in a
157+
/// specific compilation unit. `FileMetadata` descriptors are defined using this
158+
/// scope.
159+
///
160+
/// These descriptors are collected by a named metadata node `!llvm.dbg.cu`.
161+
/// They keep track of global variables, type information, and imported entities
162+
/// (declarations and namespaces).
163+
public struct CompileUnitMetadata: DIScope {
164+
internal let llvm: LLVMMetadataRef
165+
166+
public func asMetadata() -> LLVMMetadataRef {
167+
return llvm
168+
}
169+
170+
public init(llvm: LLVMMetadataRef) {
171+
self.llvm = llvm
172+
}
173+
}
174+
175+
176+
/// `FileMetadata` nodes represent files.
177+
///
178+
/// The file name does not necessarily have to be a proper file path. For
179+
/// example, it can include additional slash-separated path components.
180+
public struct FileMetadata: DIScope {
18181
internal let llvm: LLVMMetadataRef
19182

20183
public func asMetadata() -> LLVMMetadataRef {
21184
return llvm
22185
}
186+
187+
public init(llvm: LLVMMetadataRef) {
188+
self.llvm = llvm
189+
}
23190
}
24191

25-
public struct FileMetadata: Metadata {
192+
/// `DIBasicType` nodes represent primitive types, such as `int`, `bool` and
193+
/// `float`.
194+
///
195+
/// Basic types carry an encoding describing the details of the type to
196+
/// influence how it is presented in debuggers. LLVM currently supports
197+
/// specific DWARF "Attribute Type Encodings" that are enumerated in
198+
/// `DIAttributeTypeEncoding`.
199+
public struct DIBasicType: DIType {
26200
internal let llvm: LLVMMetadataRef
27201

28202
public func asMetadata() -> LLVMMetadataRef {
29203
return llvm
30204
}
205+
206+
public init(llvm: LLVMMetadataRef) {
207+
self.llvm = llvm
208+
}
31209
}
32210

33-
public struct Scope: Metadata {
211+
/// `DISubroutineType` nodes represent subroutine types.
212+
///
213+
/// Subroutine types are meant to mirror their formal declarations in source:
214+
/// arguments are represented in order. The return type is optional and meant
215+
/// to represent the concept of `void` in C-like languages.
216+
public struct DISubroutineType: DIType {
34217
internal let llvm: LLVMMetadataRef
35218

36219
public func asMetadata() -> LLVMMetadataRef {
37220
return llvm
38221
}
222+
223+
public init(llvm: LLVMMetadataRef) {
224+
self.llvm = llvm
225+
}
39226
}
40227

41-
public struct Macro: Metadata {
228+
/// `LexicalBlockMetadata` nodes describe nested blocks within a subprogram. The
229+
/// line number and column numbers are used to distinguish two lexical blocks at
230+
/// same depth.
231+
///
232+
/// Usually lexical blocks are distinct to prevent node merging based on
233+
/// operands.
234+
public struct LexicalBlockMetadata: DIScope {
42235
internal let llvm: LLVMMetadataRef
43236

44237
public func asMetadata() -> LLVMMetadataRef {
45238
return llvm
46239
}
240+
241+
public init(llvm: LLVMMetadataRef) {
242+
self.llvm = llvm
243+
}
47244
}
48245

49-
public struct DIModule: Metadata {
246+
/// `LexicalBlockFile` nodes are used to discriminate between sections of a
247+
/// lexical block. The file field can be changed to indicate textual inclusion,
248+
/// or the discriminator field can be used to discriminate between control flow
249+
/// within a single block in the source language.
250+
public struct LexicalBlockFileMetadata: DIScope {
50251
internal let llvm: LLVMMetadataRef
51252

52253
public func asMetadata() -> LLVMMetadataRef {
53254
return llvm
54255
}
256+
257+
public init(llvm: LLVMMetadataRef) {
258+
self.llvm = llvm
259+
}
55260
}
56261

57-
public struct DIExpression: Metadata {
262+
/// `LocalVariableMetadata` nodes represent local variables and function
263+
/// parameters in the source language.
264+
public struct LocalVariableMetadata: Metadata {
58265
internal let llvm: LLVMMetadataRef
59266

60267
public func asMetadata() -> LLVMMetadataRef {
61268
return llvm
62269
}
270+
271+
public init(llvm: LLVMMetadataRef) {
272+
self.llvm = llvm
273+
}
63274
}
64275

276+
/// `ObjectiveCPropertyMetadata` nodes represent Objective-C property nodes.
277+
public struct ObjectiveCPropertyMetadata: Metadata {
278+
internal let llvm: LLVMMetadataRef
65279

66-
public struct DebugLocation: Metadata {
280+
public func asMetadata() -> LLVMMetadataRef {
281+
return llvm
282+
}
283+
284+
public init(llvm: LLVMMetadataRef) {
285+
self.llvm = llvm
286+
}
287+
}
288+
289+
/// `ImportedEntityMetadata` nodes represent entities (such as modules) imported
290+
/// into a compile unit.
291+
public struct ImportedEntityMetadata: DIType {
67292
internal let llvm: LLVMMetadataRef
68293

69294
public func asMetadata() -> LLVMMetadataRef {
70295
return llvm
71296
}
297+
298+
public init(llvm: LLVMMetadataRef) {
299+
self.llvm = llvm
300+
}
301+
}
302+
303+
public struct FunctionMetadata: DIScope {
304+
internal let llvm: LLVMMetadataRef
305+
306+
public func asMetadata() -> LLVMMetadataRef {
307+
return llvm
308+
}
309+
310+
public init(llvm: LLVMMetadataRef) {
311+
self.llvm = llvm
312+
}
313+
}
314+
315+
public struct ModuleMetadata: DIScope {
316+
internal let llvm: LLVMMetadataRef
317+
318+
public func asMetadata() -> LLVMMetadataRef {
319+
return llvm
320+
}
321+
322+
public init(llvm: LLVMMetadataRef) {
323+
self.llvm = llvm
324+
}
325+
}
326+
327+
public struct NameSpaceMetadata: DIScope {
328+
internal let llvm: LLVMMetadataRef
329+
330+
public func asMetadata() -> LLVMMetadataRef {
331+
return llvm
332+
}
333+
334+
public init(llvm: LLVMMetadataRef) {
335+
self.llvm = llvm
336+
}
72337
}

0 commit comments

Comments
 (0)