8000 Merge pull request #203 from CodaFi/doctor-my-eyes · llvm-swift/LLVMSwift@c469d30 · GitHub
[go: up one dir, main page]

Skip to content

Commit c469d30

Browse files
authored
Merge pull request #203 from CodaFi/doctor-my-eyes
[NFC] Improve Doc Comments For Major Components
2 parents 5ac81ca + 2f05f12 commit c469d30

File tree

9 files changed

+647
-260
lines changed

9 files changed

+647
-260
lines changed

Sources/LLVM/Alias.swift

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,29 @@ import cllvm
44

55
/// An `Alias` represents a global alias in an LLVM module - a new symbol and
66
/// corresponding metadata for an existing global value.
7+
///
8+
/// An `Alias`, unlike a function or global variable declaration, does not
9+
/// create any new data in the resulting object file. It is merely a new name
10+
/// for an existing symbol or constant. The aliased value (the aliasee) must
11+
/// be either another global value like a function, global variable, or even
12+
/// another alias, or it must be a constant expression.
13+
///
14+
/// Linkers make no guarantees that aliases will be preserved in the final
15+
/// object file. Aliases where the address is known to be relevant should be
16+
/// marked with the appropriate `UnnamedAddressKind` value. If this value is
17+
/// not `none`, the alias is guaranteed to have the same address as the aliasee.
18+
/// Else, the alias is guaranteed to point to the same content as the aliasee,
19+
/// but may reside at a different address.
20+
///
21+
/// If the aliasee is a constant value, LLVM places additional restrictions on
22+
/// its content in order to maintain compatibility with the expected behavior of
23+
/// most linkers:
24+
///
25+
/// - The constant expression may not involve aliases with weak linkage. Such
26+
/// weak aliases cannot be guaranteed to be stable in the final object file.
27+
/// - The constant expression may not involve global values requiring a
28+
/// relocation such as a global function or global variable declared but not
29+
/// defined within its module.
730
public struct Alias: IRGlobal {
831
internal let llvm: LLVMValueRef
932

@@ -12,7 +35,9 @@ public struct Alias: IRGlobal {
1235
return llvm
1336
}
1437

15-
/// Access the target value of this alias.
38+
/// The target value of this alias.
39+
///
40+
/// The aliasee is required to be another global value or constant
1641
public var aliasee: IRValue {
1742
get { return LLVMAliasGetAliasee(llvm) }
1843
set { LLVMAliasSetAliasee(llvm, newValue.asLLVM()) }

Sources/LLVM/BasicBlock.swift

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,72 @@ import cllvm
55
/// A `BasicBlock` represents a basic block in an LLVM IR program. A basic
66
/// block contains a sequence of instructions, a pointer to its parent block and
77
/// its follower block, and an optional label that gives the basic block an
8-
/// entry in the symbol table.
8+
/// entry in the symbol table. Because of this label, the type of every basic
9+
/// block is `LabelType`.
910
///
1011
/// A basic block can be thought of as a sequence of instructions, and indeed
11-
/// its member instructions may be iterated over with a `for-in` loop.
12+
/// its member instructions may be iterated over with a `for-in` loop. A well-
13+
/// formed basic block has as its last instruction a "terminator" that produces
14+
/// a transfer of control flow and possibly yields a value. All other
15+
/// instructions in the middle of the basic block may not be "terminator"
16+
/// instructions. Basic blocks are not required to be well-formed until
17+
/// code generation is complete.
1218
///
13-
/// The first basic block in a function is special in two ways: it is
14-
/// immediately executed on entrance to the function, and it is not allowed to
15-
/// have predecessor basic blocks (i.e. there can not be any branches to the
16-
/// entry block of a function). Because the block can have no predecessors, it
17-
/// also cannot have any PHI nodes.
19+
/// Creating a Basic Block
20+
/// ======================
21+
///
22+
/// By default, the initializer for a basic block merely creates the block but
23+
/// does not associate it with a function.
24+
///
25+
/// let module = Module(name: "Example")
26+
/// let fun = builder.addFunction("example",
27+
/// type: FunctionType(argTypes: [],
28+
/// returnType: VoidType()))
29+
///
30+
/// // This basic block is "floating" outside of a function.
31+
/// let floatingBB = BasicBlock(name: "floating")
32+
/// // Until we associate it with a function by calling `Function.append(_:)`.
33+
/// fun.append(floatingBB)
34+
///
35+
/// A basic block may be created and automatically inserted at the end of a
36+
/// function by calling `Function.appendBasicBlock(named:in:)`.
37+
///
38+
/// let module = Module(name: "Example")
39+
/// let fun = builder.addFunction("example",
40+
/// type: FunctionType(argTypes: [],
41+
/// returnType: VoidType()))
42+
///
43+
/// // This basic block is "attached" to the example function.
44+
/// let attachedBB = fun.appendBasicBlock(named: "attached")
45+
///
46+
/// The Address of a Basic Block
47+
/// ============================
48+
///
49+
/// Basic blocks (except the entry block) may have their labels appear in the
50+
/// symbol table. Naturally, these labels are associated with address values
51+
/// in the final object file. The value of that address may be accessed for the
52+
/// purpose of an indirect call or a direct comparisson by calling
53+
/// `Function.address(of:)` and providing one of the function's child blocks as
54+
/// an argument. Providing any other basic block outside of the function as an
55+
/// argument value is undefined.
56+
///
57+
/// The Entry Block
58+
/// ===============
59+
///
60+
/// The first basic block (the entry block) in a `Function` is special:
61+
///
62+
/// - The entry block is immediately executed when the flow of control enters
63+
/// its parent function.
64+
/// - The entry block is not allowed to have predecessor basic blocks
65+
/// (i.e. there cannot be any branches to the entry block of a function).
66+
/// - The address of the entry block is not a well-defined value.
67+
/// - The entry block cannot have PHI nodes. This is enforced structurally,
68+
/// as the entry block can have no predecessor blocks to serve as operands
69+
/// to the PHI node.
70+
/// - Static `alloca` instructions situated in the entry block are treated
71+
/// specially by most LLVM backends. For example, FastISel keeps track of
72+
/// static `alloca` values in the entry block to more efficiently reference
73+
/// them from the base pointer of the stack frame.
1874
public struct BasicBlock: IRValue {
1975
internal let llvm: LLVMBasicBlockRef
2076

Sources/LLVM/Context.swift

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#if SWIFT_PACKAGE
2+
import cllvm
3+
#endif
4+
5+
/// A `Context` is an LLVM compilation session environment.
6+
///
7+
/// A `Context` is a container for the global state of an execution of the
8+
/// LLVM environment and tooling. It contains independent copies of global and
9+
/// module-level entities like types, metadata attachments, and constants.
10+
///
11+
/// An LLVM context is needed for interacting with LLVM in a concurrent
12+
/// environment. Because a context maintains state independent of any other
13+
/// context, it is recommended that each thread of execution be assigned a unique
14+
/// context. LLVM's core infrastructure and API provides no locking guarantees
15+
/// and no atomicity guarantees.
16+
public class Context {
17+
internal let llvm: LLVMContextRef
18+
private let ownsContext: Bool
19+
20+
/// Retrieves the global context instance.
21+
///
22+
/// The global context is an particularly convenient instance managed by LLVM
23+
/// itself. It is the default context provided for any operations that
24+
/// require it.
25+
///
26+
/// - WARNING: Failure to specify the correct context in concurrent
27+
/// environments can lead to data corruption. In general, it is always
28+
/// recommended that each thread of execution attempting to access the LLVM
29+
/// API have its own `Context` instance, rather than rely on this global
30+
/// context.
31+
public static let global = Context(llvm: LLVMGetGlobalContext()!)
32+
33+
/// Creates a new `Context` object.
34+
public init() {
35+
llvm = LLVMContextCreate()
36+
ownsContext = true
37+
}
38+
39+
/// Creates a `Context` object from an `LLVMContextRef` object.
40+
public init(llvm: LLVMContextRef, ownsContext: Bool = false) {
41+
self.llvm = llvm
42+
self.ownsContext = ownsContext
43+
}
44+
45+
/// Returns whether the given context is set to discard all value names.
46+
///
47+
/// If true, only the names of GlobalValue objects will be available in
48+
/// the IR. This can be used to save memory and processing time, especially
49+
/// in release environments.
50+
public var discardValueNames: Bool {
51+
get { return LLVMContextShouldDiscardValueNames(self.llvm) != 0 }
52+
set { LLVMContextSetDiscardValueNames(self.llvm, newValue.llvm) }
53+
}
54+
55+
/// Deinitialize this value and dispose of its resources.
56+
deinit {
57+
guard self.ownsContext else {
58+
return
59+
}
60+
LLVMContextDispose(self.llvm)
61+
}
62+
}

Sources/LLVM/Function.swift

Lines changed: 89 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,91 @@
11
#if SWIFT_PACKAGE
22
import cllvm
3+
import llvmshims
34
#endif
45

56
/// A `Function` represents a named function body in LLVM IR source. Functions
67
/// in LLVM IR encapsulate a list of parameters and a sequence of basic blocks
78
/// and provide a way to append to that sequence to build out its body.
9+
///
10+
/// A LLVM function definition contains a list of basic blocks, starting with
11+
/// a privileged first block called the "entry block". After the entry blocks'
12+
/// terminating instruction come zero or more other basic blocks. The path the
13+
/// flow of control can potentially take, from each block to its terminator
14+
/// and on to other blocks, forms the "Control Flow Graph" (CFG) for the
15+
/// function. The nodes of the CFG are the basic blocks, and the edges are
16+
/// directed from the terminator instruction of one block to any number of
17+
/// potential target blocks.
18+
///
19+
/// Additional basic blocks may be created and appended to the function at
20+
/// any time.
21+
///
22+
/// let module = Module(name: "Example")
23+
/// let builder = IRBuilder(module: module)
24+
/// let fun = builder.addFunction("example",
25+
/// type: FunctionType(argTypes: [],
26+
/// returnType: VoidType()))
27+
/// // Create and append the entry block
28+
/// let entryBB = fun.appendBasicBlock(named: "entry")
29+
/// // Create and append a standalone basic block
30+
/// let freestanding = BasicBlock(name: "freestanding")
31+
/// fun.append(freestanding)
32+
///
33+
/// An LLVM function always has the type `FunctionType`. This type is used to
34+
/// determine the number and kind of parameters to the function as well as its
35+
/// return value, if any. The parameter values, which would normally enter
36+
/// the entry block, are instead attached to the function and are accessible
37+
/// via the `parameters` property.
38+
///
39+
/// Calling Convention
40+
/// ==================
41+
///
42+
/// By default, all functions in LLVM are invoked with the C calling convention
43+
/// but the exact calling convention of both a function declaration and a
44+
/// `call` instruction are fully configurable.
45+
///
46+
/// let module = Module(name: "Example")
47+
/// let builder = IRBuilder(module: module)
48+
/// let fun = builder.addFunction("example",
49+
/// type: FunctionType(argTypes: [],
50+
/// returnType: VoidType()))
51+
/// // Switch to swiftcc
52+
/// fun.callingConvention = .swift
53+
///
54+
/// The calling convention of a function and a corresponding call instruction
55+
/// must match or the result is undefined.
56+
///
57+
/// Sections
58+
/// ========
59+
///
60+
/// A function may optionally state the section in the object file it
61+
/// should reside in through the use of a metadata attachment. This can be
62+
/// useful to satisfy target-specific data layout constraints, or to provide
63+
/// some hints to optimizers and linkers. LLVMSwift provides a convenience
64+
/// object called an `MDBuilder` to assist in the creation of this metadata.
65+
///
66+
/// let mdBuilder = MDBuilder()
67+
/// // __attribute__((hot))
68+
/// let hotAttr = mdBuilder.buildFunctionSectionPrefix(".hot")
69+
///
70+
/// let module = Module(name: "Example")
71+
/// let builder = IRBuilder(module: module)
72+
/// let fun = builder.addFunction("example",
73+
/// type: FunctionType(argTypes: [],
74+
/// returnType: VoidType()))
75+
/// // Attach the metadata
76+
/// fun.addMetadata(hotAttr, kind: .sectionPrefix)
77+
///
78+
/// For targets that support it, a function may also specify a COMDAT section.
79+
///
80+
/// fun.comdat = module.comdat(named: "example")
81+
///
82+
/// Debug Information
83+
/// =================
84+
///
85+
/// A function may also carry debug information through special subprogram
86+
/// nodes. These nodes are intended to capture the structure of the function
87+
/// as it appears in the source so that it is available for inspection by a
88+
/// debugger. See `DIBuilderr.buildFunction` for more information.
889
public class Function: IRGlobal {
990
internal let llvm: LLVMValueRef
1091
internal init(llvm: LLVMValueRef) {
@@ -26,17 +107,6 @@ public class Function: IRGlobal {
26107
}
27108

28109
/// Retrieves the entry block of this function.
29-
///
30-
/// The first basic block in a function is special in two ways: it is
31-
/// immediately executed on entrance to the function, and it is not allowed to
32-
/// have predecessor basic blocks (i.e. there can not be any branches to the
33-
/// entry block of a function). Because the block can have no predecessors, it
34-
/// also cannot have any PHI nodes.
35-
///
36-
/// The entry block is also special in that any static allocas emitted into it
37-
/// influence the layout of the stack frame of the function at code generation
38-
/// time. It is therefore often more efficient to emit static allocas in the
39-
/// entry block than anywhere else in the function.
40110
public var entryBlock: BasicBlock? {
41111
guard let blockRef = LLVMGetEntryBasicBlock(llvm) else { return nil }
42112
return BasicBlock(llvm: blockRef)
@@ -78,7 +148,7 @@ public class Function: IRGlobal {
78148

79149
/// Computes the address of the specified basic block in this function.
80150
///
81-
/// Taking the address of the entry block is illegal.
151+
/// - WARNING: Taking the address of the entry block is illegal.
82152
///
83153
/// This value only has defined behavior when used as an operand to the
84154
/// `indirectbr` instruction, or for comparisons against null. Pointer
@@ -170,6 +240,13 @@ public class Function: IRGlobal {
170240
return BasicBlock(llvm: block)
171241
}
172242

243+
/// Appends the named basic block to the body of this function.
244+
///
245+
/// - parameter basicBlock: The block to append.
246+
public func append(_ basicBlock: BasicBlock) {
247+
LLVMAppendExistingBasicBlock(llvm, basicBlock.asLLVM())
248+
}
249+
173250
/// Deletes the function from its containing module.
174251
/// - note: This does not remove calls to this function from the
175252
/// module. Ensure you have removed all instructions that reference

0 commit comments

Comments
 (0)
0