Skip to content

Commit 35dc61a

Browse files
CodaFiharlanhaskins
authored andcommitted
Add accessors for linkage. (#27)
* Add accessors for linkage. Obsolete linkage is intentionally left out for obvious reasons. * Split linkage into its own file
1 parent 2ce14c8 commit 35dc61a

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed

Sources/LLVM/Function.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ public class Function: IRValue {
107107
LLVMDeleteFunction(llvm)
108108
}
109109

110+
/// Retrieves the linkage information for this function.
111+
public var linkage: Linkage {
112+
get { return Linkage(llvm: LLVMGetLinkage(asLLVM())) }
113+
set { LLVMSetLinkage(asLLVM(), newValue.llvm) }
114+
}
115+
110116
/// Retrieves the underlying LLVM value object.
111117
public func asLLVM() -> LLVMValueRef {
112118
return llvm

Sources/LLVM/Global.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ public struct Global: IRValue {
3333
set { LLVMSetThreadLocal(asLLVM(), newValue.llvm) }
3434
}
3535

36+
/// Retrieves the linkage information for this global value.
37+
public var linkage: Linkage {
38+
get { return Linkage(llvm: LLVMGetLinkage(asLLVM())) }
39+
set { LLVMSetLinkage(asLLVM(), newValue.llvm) }
40+
}
41+
3642
/// Deletes the global variable from its containing module.
3743
/// - note: This does not remove references to this global from the
3844
/// module. Ensure you have removed all insructions that reference

Sources/LLVM/Linkage.swift

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import cllvm
2+
3+
/// `Linkage` enumerates the supported kinds of linkage for global values. All
4+
/// global variables and functions have a linkage.
5+
public enum Linkage {
6+
/// Externally visible function. This is the default linkage.
7+
///
8+
/// If none of the other linkages are specified, the global is externally
9+
/// visible, meaning that it participates in linkage and can be used to
10+
/// resolve external symbol references.
11+
case external
12+
/// Available for inspection, not emission.
13+
///
14+
/// Globals with "available_externally" linkage are never emitted into the
15+
/// object file corresponding to the LLVM module. From the linker’s
16+
/// perspective, an available_externally global is equivalent to an external
17+
/// declaration. They exist to allow inlining and other optimizations to take
18+
/// place given knowledge of the definition of the global, which is known to
19+
/// be somewhere outside the module. Globals with available_externally linkage
20+
/// are allowed to be discarded at will, and allow inlining and other
21+
/// optimizations. This linkage type is only allowed on definitions, not
22+
/// declarations.
23+
case availableExternally
24+
/// Keep one copy of function when linking.
25+
///
26+
/// Globals with "linkonce" linkage are merged with other globals of the same
27+
/// name when linkage occurs. This can be used to implement some forms of
28+
/// inline functions, templates, or other code which must be generated in each
29+
/// translation unit that uses it, but where the body may be overridden with a
30+
/// more definitive definition later. Unreferenced linkonce globals are
31+
/// allowed to be discarded. Note that linkonce linkage does not actually
32+
/// allow the optimizer to inline the body of this function into callers
33+
/// because it doesn’t know if this definition of the function is the
34+
/// definitive definition within the program or whether it will be overridden
35+
/// by a stronger definition.
36+
case linkOnceAny
37+
/// Keep one copy of function when linking but enable inlining and
38+
/// other optimizations.
39+
///
40+
/// Some languages allow differing globals to be merged, such as two functions
41+
/// with different semantics. Other languages, such as C++, ensure that only
42+
/// equivalent globals are ever merged (the "one definition rule" — "ODR").
43+
/// Such languages can use the linkonce_odr and weak_odr linkage types to
44+
/// indicate that the global will only be merged with equivalent globals.
45+
/// These linkage types are otherwise the same as their non-odr versions.
46+
case linkOnceODR
47+
/// Keep one copy of function when linking (weak).
48+
///
49+
/// "weak" linkage has the same merging semantics as linkonce linkage, except
50+
/// that unreferenced globals with weak linkage may not be discarded. This is
51+
/// used for globals that are declared "weak" in C source code.
52+
case weakAny
53+
/// Keep one copy of function when linking but apply "One Definition Rule"
54+
/// semantics.
55+
///
56+
/// Some languages allow differing globals to be merged, such as two functions
57+
/// with different semantics. Other languages, such as C++, ensure that only
58+
/// equivalent globals are ever merged (the "one definition rule" — "ODR").
59+
/// Such languages can use the linkonce_odr and weak_odr linkage types to
60+
/// indicate that the global will only be merged with equivalent globals.
61+
/// These linkage types are otherwise the same as their non-odr versions.
62+
case weakODR
63+
/// Special purpose, only applies to global arrays.
64+
///
65+
/// "appending" linkage may only be applied to global variables of pointer to
66+
/// array type. When two global variables with appending linkage are linked
67+
/// together, the two global arrays are appended together. This is the LLVM,
68+
/// typesafe, equivalent of having the system linker append together
69+
/// "sections" with identical names when .o files are linked.
70+
///
71+
/// Unfortunately this doesn’t correspond to any feature in .o files, so it
72+
/// can only be used for variables like llvm.global_ctors which llvm
73+
/// interprets specially.
74+
case appending
75+
/// Rename collisions when linking (static functions).
76+
///
77+
/// Similar to private, but the value shows as a local symbol
78+
/// (`STB_LOCAL` in the case of ELF) in the object file. This corresponds to
79+
/// the notion of the `static` keyword in C.
80+
case `internal`
81+
/// Like `.internal`, but omit from symbol table.
82+
///
83+
/// Global values with "private" linkage are only directly accessible by
84+
/// objects in the current module. In particular, linking code into a module
85+
/// with an private global value may cause the private to be renamed as
86+
/// necessary to avoid collisions. Because the symbol is private to the
87+
/// module, all references can be updated. This doesn’t show up in any symbol
88+
/// table in the object file.
89+
case `private`
90+
/// Keep one copy of the function when linking, but apply ELF semantics.
91+
///
92+
/// The semantics of this linkage follow the ELF object file model: the symbol
93+
/// is weak until linked, if not linked, the symbol becomes null instead of
94+
/// being an undefined reference.
95+
case externalWeak
96+
/// Tentative definitions.
97+
///
98+
/// "common" linkage is most similar to "weak" linkage, but they are used for
99+
/// tentative definitions in C, such as "int X;" at global scope. Symbols with
100+
/// "common" linkage are merged in the same way as weak symbols, and they may
101+
/// not be deleted if unreferenced. common symbols may not have an explicit
102+
/// section, must have a zero initializer, and may not be marked ‘constant‘.
103+
/// Functions and aliases may not have common linkage.
104+
case common
105+
106+
private static let linkageMapping: [Linkage: LLVMLinkage] = [
107+
.external: LLVMExternalLinkage,
108+
.availableExternally: LLVMAvailableExternallyLinkage,
109+
.linkOnceAny: LLVMLinkOnceAnyLinkage, .linkOnceODR: LLVMLinkOnceODRLinkage,
110+
.weakAny: LLVMWeakAnyLinkage, .weakODR: LLVMWeakODRLinkage,
111+
.appending: LLVMAppendingLinkage, .`internal`: LLVMInternalLinkage,
112+
.`private`: LLVMPrivateLinkage, .externalWeak: LLVMExternalWeakLinkage,
113+
.common: LLVMCommonLinkage,
114+
]
115+
116+
internal init(llvm: LLVMLinkage) {
117+
switch llvm {
118+
case LLVMExternalLinkage: self = .external
119+
case LLVMAvailableExternallyLinkage: self = .availableExternally
120+
case LLVMLinkOnceAnyLinkage: self = .linkOnceAny
121+
case LLVMLinkOnceODRLinkage: self = .linkOnceODR
122+
case LLVMWeakAnyLinkage: self = .weakAny
123+
case LLVMWeakODRLinkage: self = .weakODR
124+
case LLVMAppendingLinkage: self = .appending
125+
case LLVMInternalLinkage: self = .internal
126+
case LLVMPrivateLinkage: self = .private
127+
case LLVMExternalWeakLinkage: self = .externalWeak
128+
case LLVMCommonLinkage: self = .common
129+
default: fatalError("unknown linkage type \(llvm)")
130+
}
131+
}
132+
133+
/// Retrieves the corresponding `LLVMLinkage`.
134+
public var llvm: LLVMLinkage {
135+
return Linkage.linkageMapping[self]!
136+
}
137+
}

0 commit comments

Comments
 (0)