Skip to content

Commit 9ce5f07

Browse files
authored
Merge pull request #123 from CodaFi/inertia
Enable Inert References
2 parents d734db6 + 7ed1b52 commit 9ce5f07

File tree

5 files changed

+145
-2
lines changed

5 files changed

+145
-2
lines changed

Sources/LLVM/Constant.swift

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,43 @@ extension Constant where Repr == Struct {
165165
}
166166
}
167167

168+
// MARK: Truncation
168169

170+
extension Constant where Repr == Signed {
171+
/// Creates a constant truncated to a given integral type.
172+
///
173+
/// - parameter type: The type to truncate towards.
174+
///
175+
/// - returns: A const value representing this value truncated to the given
176+
/// integral type's bitwidth.
177+
public func truncate(to type: IntType) -> Constant<Signed> {
178+
return Constant<Signed>(llvm: LLVMConstTrunc(llvm, type.asLLVM()))
179+
}
180+
}
181+
182+
extension Constant where Repr == Unsigned {
183+
/// Creates a constant truncated to a given integral type.
184+
///
185+
/// - parameter type: The type to truncate towards.
186+
///
187+
/// - returns: A const value representing this value truncated to the given
188+
/// integral type's bitwidth.
189+
public func truncate(to type: IntType) -> Constant<Unsigned> {
190+
return Constant<Unsigned>(llvm: LLVMConstTrunc(llvm, type.asLLVM()))
191+
}
192+
}
193+
194+
extension Constant where Repr == Floating {
195+
/// Creates a constant truncated to a given floating type.
196+
///
197+
/// - parameter type: The type to truncate towards.
198+
///
199+
/// - returns: A const value representing this value truncated to the given
200+
/// floating type's bitwidth.
201+
public func truncate(to type: FloatType) -> Constant<Floating> {
202+
return Constant<Floating>(llvm: LLVMConstFPTrunc(llvm, type.asLLVM()))
203+
}
204+
}
169205

170206
// MARK: Arithmetic Operations
171207

@@ -936,6 +972,23 @@ extension Constant {
936972
}
937973
}
938974

975+
// MARK: Constant Pointer To Integer
976+
977+
extension Constant where Repr: IntegralConstantRepresentation {
978+
/// Creates a constant pointer-to-integer operation to convert the given constant
979+
/// global pointer value to the given integer type.
980+
///
981+
/// - parameter val: The pointer value.
982+
/// - parameter intType: The destination integer type.
983+
///
984+
/// - returns: An constant value representing the constant value of the given
985+
/// pointer converted to the given integer type.
986+
public static func pointerToInt(_ val: IRGlobal, _ intType: IntType) -> Constant {
987+
precondition(val.isConstant, "May only convert global constant pointers to integers")
988+
return Constant<Repr>(llvm: LLVMConstPtrToInt(val.asLLVM(), intType.asLLVM()))
989+
}
990+
}
991+
939992
// MARK: Struct Operations
940993

941994
extension Constant where Repr == Struct {

Sources/LLVM/IRGlobal.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ extension IRGlobal {
3232
set { LLVMSetDLLStorageClass(asLLVM(), newValue.llvm) }
3333
}
3434

35+
/// Retrieves an indicator for the significance of a global value's address.
36+
public var unnamedAddressKind: UnnamedAddressKind {
37+
get { return UnnamedAddressKind(llvm: LLVMHasUnnamedAddr(asLLVM())) }
38+
set { LLVMSetUnnamedAddr(asLLVM(), newValue.llvm) }
39+
}
40+
3541
/// Retrieves the section associated with the symbol that will eventually be
3642
/// emitted for this global value.
3743
///

Sources/LLVM/Linkage.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,49 @@ public enum StorageClass {
216216
return StorageClass.storageMapping[self]!
217217
}
218218
}
219+
220+
/// Enumerates values representing whether or not this global value's address
221+
/// is significant in this module or the program at large. A global value's
222+
/// address is considered significant if it is referenced by any module in the
223+
/// final program.
224+
///
225+
/// This attribute is intended to be used only by the code generator and LTO to
226+
/// allow the linker to decide whether the global needs to be in the symbol
227+
/// table. Constant global values with unnamed addresses and identical
228+
/// initializers may be merged by LLVM. Note that a global value with an
229+
/// unnamed address may be merged with a global value with a significant address
230+
/// resulting in a global value with a significant address.
231+
public enum UnnamedAddressKind {
232+
/// Indicates that the address of this global value is significant
233+
/// in this module.
234+
case none
235+
236+
/// Indicates that the address of this global value is not significant to the
237+
/// current module but it may or may not be significant to another module;
238+
/// only the content of the value is known to be significant within the
239+
/// current module.
240+
// case local
241+
242+
/// Indicates that the address of this global value is not significant to the
243+
/// current module or any other module; only the content of the value
244+
/// is significant globally.
245+
case global
246+
247+
private static let unnamedAddressMapping: [UnnamedAddressKind: LLVMBool] = [
248+
.none: LLVMBool(0),
249+
// .local: LLVMBool(1),
250+
.global: LLVMBool(1),
251+
]
252+
253+
internal init(llvm: LLVMBool) {
254+
switch llvm {
255+
case 0: self = .none
256+
case 1: self = .global
257+
default: fatalError("unknown unnamed address kind \(llvm)")
258+
}
259+
}
260+
261+
internal var llvm: LLVMBool {
262+
return UnnamedAddressKind.unnamedAddressMapping[self]!
263+
}
264+
}

Tests/LLVMTests/IRGlobalSpec.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import LLVM
2+
import XCTest
3+
import FileCheck
4+
import Foundation
5+
6+
class IRGlobalSpec : XCTestCase {
7+
func testIRInertGlobal() {
8+
XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["IRINERTGLOBAL"]) {
9+
// IRINERTGLOBAL: ; ModuleID = '[[ModuleName:IRInertGlobalTest]]'
10+
// IRINERTGLOBAL-NEXT: source_filename = "[[ModuleName]]"
11+
let module = Module(name: "IRInertGlobalTest")
12+
let builder = IRBuilder(module: module)
13+
// IRINERTGLOBAL: @external_global = external constant i32
14+
var extGlobal = builder.addGlobal("external_global", type: IntType.int32)
15+
extGlobal.isGlobalConstant = true
16+
// IRINERTGLOBAL: @got.external_global = private unnamed_addr constant i32* @external_global
17+
var gotGlobal = builder.addGlobal("got.external_global",
18+
initializer: extGlobal)
19+
gotGlobal.linkage = .`private`
20+
gotGlobal.unnamedAddressKind = .global
21+
gotGlobal.isGlobalConstant = true
22+
23+
// IRINERTGLOBAL: @external_relative_reference = global i32 trunc (i64 sub (i64 ptrtoint (i32** @got.external_global to i64), i64 ptrtoint (i32* @external_relative_reference to i64)) to i32)
24+
var ext_relative_reference = builder.addGlobal("external_relative_reference", type: IntType.int32)
25+
ext_relative_reference.initializer = Constant<Unsigned>.pointerToInt(gotGlobal, .int64)
26+
.subtracting(Constant<Unsigned>.pointerToInt(ext_relative_reference, .int64)).truncate(to: .int32)
27+
module.dump()
28+
})
29+
}
30+
31+
#if !os(macOS)
32+
static var allTests = testCase([
33+
("testIRInertGlobal", testIRInertGlobal),
34+
])
35+
#endif
36+
}
37+

Tests/LinuxMain.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import XCTest
44

55
#if !os(macOS)
66
XCTMain([
7-
IRBuilderSpec.allTests,
87
ConstantSpec.allTests,
8+
FileCheckSpec.allTests,
9+
IRBuilderSpec.allTests,
910
IRExceptionSpec.allTests,
11+
IRGlobalSpec.allTests,
1012
IROperationSpec.allTests,
11-
FileCheckSpec.allTests,
1213
JITSpec.allTests,
1314
ModuleLinkSpec.allTests,
1415
])

0 commit comments

Comments
 (0)