Skip to content

Commit

Permalink
Opaque Pointer Cleanup
Browse files Browse the repository at this point in the history
Finish the migration to opaque pointers.

* Fixup the singular load in the README
* Fixup the test suite
* Move the deprecations into a convenient extension
  • Loading branch information
CodaFi committed Jun 5, 2019
1 parent 15f1656 commit b40580c
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 164 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Package.resolved
Package.pins
/*.xcodeproj
/build
/.swiftpm
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ phi.addIncoming([
(elseVal, elseBB),
])
builder.buildStore(phi, to: local)
let ret = builder.buildLoad(local, name: "ret")
let ret = builder.buildLoad(local, type: FloatType.double, name: "ret")
builder.buildRet(ret)
```

Expand Down
163 changes: 84 additions & 79 deletions Sources/LLVM/IRBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1078,27 +1078,6 @@ extension IRBuilder {
return storeInst
}

/// Build a load instruction that loads a value from the location in the
/// given value.
///
/// - parameter ptr: The pointer value to load from.
/// - parameter ordering: The ordering effect of the fence for this load,
/// if any. Defaults to a nonatomic load.
/// - parameter volatile: Whether this is a load from a volatile memory location.
/// - parameter alignment: The alignment of the access.
/// - parameter name: The name for the newly inserted instruction.
///
/// - returns: A value representing the result of a load from the given
/// pointer value.
@available(*, deprecated, message: "Use buildLoad(type:ptr:ordering:volatile:alignment:name) instead")
public func buildLoad(_ ptr: IRValue, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false, alignment: Alignment = .zero, name: String = "") -> IRInstruction {
let loadInst = LLVMBuildLoad(llvm, ptr.asLLVM(), name)!
LLVMSetOrdering(loadInst, ordering.llvm)
LLVMSetVolatile(loadInst, volatile.llvm)
LLVMSetAlignment(loadInst, alignment.rawValue)
return loadInst
}

/// Build a load instruction that loads a value from the location in the
/// given value.
///
Expand All @@ -1119,29 +1098,7 @@ extension IRBuilder {
LLVMSetAlignment(loadInst, alignment.rawValue)
return loadInst
}

/// Build a `GEP` (Get Element Pointer) instruction with a resultant value
/// that is undefined if the address is outside the actual underlying
/// allocated object and not the address one-past-the-end.
///
/// The `GEP` instruction is often the source of confusion. LLVM [provides a
/// document](http://llvm.org/docs/GetElementPtr.html) to answer questions
/// around its semantics and correct usage.
///
/// - parameter ptr: The base address for the index calculation.
/// - parameter indices: A list of indices that indicate which of the elements
/// of the aggregate object are indexed.
/// - parameter name: The name for the newly inserted instruction.
///
/// - returns: A value representing the address of a subelement of the given
/// aggregate data structure value.
@available(*, deprecated, message: "Use buildInBoundsGEP(type:ptr:indices:name) instead")
public func buildInBoundsGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue {
var vals = indices.map { $0.asLLVM() as Optional }
return vals.withUnsafeMutableBufferPointer { buf in
return LLVMBuildInBoundsGEP(llvm, ptr.asLLVM(), buf.baseAddress, UInt32(buf.count), name)
}
}


/// Build a `GEP` (Get Element Pointer) instruction with a resultant value
/// that is undefined if the address is outside the actual underlying
Expand All @@ -1166,27 +1123,6 @@ extension IRBuilder {
}
}

/// Build a GEP (Get Element Pointer) instruction.
///
/// The `GEP` instruction is often the source of confusion. LLVM [provides a
/// document](http://llvm.org/docs/GetElementPtr.html) to answer questions
/// around its semantics and correct usage.
///
/// - parameter ptr: The base address for the index calculation.
/// - parameter indices: A list of indices that indicate which of the elements
/// of the aggregate object are indexed.
/// - parameter name: The name for the newly inserted instruction.
///
/// - returns: A value representing the address of a subelement of the given
/// aggregate data structure value.
@available(*, deprecated, message: "Use buildGEP(type:ptr:indices:name) instead")
public func buildGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue {
var vals = indices.map { $0.asLLVM() as Optional }
return vals.withUnsafeMutableBufferPointer { buf in
return LLVMBuildGEP(llvm, ptr.asLLVM(), buf.baseAddress, UInt32(buf.count), name)
}
}

/// Build a GEP (Get Element Pointer) instruction.
///
/// The `GEP` instruction is often the source of confusion. LLVM [provides a
Expand All @@ -1207,20 +1143,6 @@ extension IRBuilder {
return LLVMBuildGEP2(llvm, type.asLLVM(), ptr.asLLVM(), buf.baseAddress, UInt32(buf.count), name)
}
}

/// Build a GEP (Get Element Pointer) instruction suitable for indexing into
/// a struct.
///
/// - parameter ptr: The base address for the index calculation.
/// - parameter index: The offset from the base for the index calculation.
/// - parameter name: The name for the newly inserted instruction.
///
/// - returns: A value representing the address of a subelement of the given
/// struct value.
@available(*, deprecated, message: "Use buildStructGEP(type:ptr:index:name) instead")
public func buildStructGEP(_ ptr: IRValue, index: Int, name: String = "") -> IRValue {
return LLVMBuildStructGEP(llvm, ptr.asLLVM(), UInt32(index), name)
}

/// Build a GEP (Get Element Pointer) instruction suitable for indexing into
/// a struct of a given type.
Expand Down Expand Up @@ -1993,6 +1915,89 @@ extension IRBuilder {
}
}

// MARK: Deprecated APIs

extension IRBuilder {
/// Build a load instruction that loads a value from the location in the
/// given value.
///
/// - parameter ptr: The pointer value to load from.
/// - parameter ordering: The ordering effect of the fence for this load,
/// if any. Defaults to a nonatomic load.
/// - parameter volatile: Whether this is a load from a volatile memory location.
/// - parameter alignment: The alignment of the access.
/// - parameter name: The name for the newly inserted instruction.
///
/// - returns: A value representing the result of a load from the given
/// pointer value.
@available(*, deprecated, message: "Use buildLoad(_:type:ordering:volatile:alignment:name) instead")
public func buildLoad(_ ptr: IRValue, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false, alignment: Alignment = .zero, name: String = "") -> IRInstruction {
let loadInst = LLVMBuildLoad(llvm, ptr.asLLVM(), name)!
LLVMSetOrdering(loadInst, ordering.llvm)
LLVMSetVolatile(loadInst, volatile.llvm)
LLVMSetAlignment(loadInst, alignment.rawValue)
return loadInst
}

/// Build a GEP (Get Element Pointer) instruction suitable for indexing into
/// a struct.
///
/// - parameter ptr: The base address for the index calculation.
/// - parameter index: The offset from the base for the index calculation.
/// - parameter name: The name for the newly inserted instruction.
///
/// - returns: A value representing the address of a subelement of the given
/// struct value.
@available(*, deprecated, message: "Use buildStructGEP(_:type:index:name) instead")
public func buildStructGEP(_ ptr: IRValue, index: Int, name: String = "") -> IRValue {
return LLVMBuildStructGEP(llvm, ptr.asLLVM(), UInt32(index), name)
}

/// Build a GEP (Get Element Pointer) instruction.
///
/// The `GEP` instruction is often the source of confusion. LLVM [provides a
/// document](http://llvm.org/docs/GetElementPtr.html) to answer questions
/// around its semantics and correct usage.
///
/// - parameter ptr: The base address for the index calculation.
/// - parameter indices: A list of indices that indicate which of the elements
/// of the aggregate object are indexed.
/// - parameter name: The name for the newly inserted instruction.
///
/// - returns: A value representing the address of a subelement of the given
/// aggregate data structure value.
@available(*, deprecated, message: "Use buildGEP(_:type:indices:name) instead")
public func buildGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue {
var vals = indices.map { $0.asLLVM() as Optional }
return vals.withUnsafeMutableBufferPointer { buf in
return LLVMBuildGEP(llvm, ptr.asLLVM(), buf.baseAddress, UInt32(buf.count), name)
}
}

/// Build a `GEP` (Get Element Pointer) instruction with a resultant value
/// that is undefined if the address is outside the actual underlying
/// allocated object and not the address one-past-the-end.
///
/// The `GEP` instruction is often the source of confusion. LLVM [provides a
/// document](http://llvm.org/docs/GetElementPtr.html) to answer questions
/// around its semantics and correct usage.
///
/// - parameter ptr: The base address for the index calculation.
/// - parameter indices: A list of indices that indicate which of the elements
/// of the aggregate object are indexed.
/// - parameter name: The name for the newly inserted instruction.
///
/// - returns: A value representing the address of a subelement of the given
/// aggregate data structure value.
@available(*, deprecated, message: "Use buildInBoundsGEP(_:type:indices:name) instead")
public func buildInBoundsGEP(_ ptr: IRValue, indices: [IRValue], name: String = "") -> IRValue {
var vals = indices.map { $0.asLLVM() as Optional }
return vals.withUnsafeMutableBufferPointer { buf in
return LLVMBuildInBoundsGEP(llvm, ptr.asLLVM(), buf.baseAddress, UInt32(buf.count), name)
}
}
}


private func lowerVector(_ type: IRType) -> IRType {
guard let vectorType = type as? VectorType else {
Expand Down
18 changes: 9 additions & 9 deletions Tests/LLVMTests/BFC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@ private func compileProgramBody(
let flushExtern = Externs.flush.resolve(builder)

var addressPointer: IRValue = cellTape.constGEP(indices: [
IntType.int32.zero(),
IntType.int32.zero()
IntType.int32.zero(), // (*self)
IntType.int32.zero() // [0]
])

/// Create an artificial typedef and variable for the current
Expand Down Expand Up @@ -291,23 +291,23 @@ private func compileProgramBody(
switch c {
case ">":
// Move right
addressPointer = builder.buildGEP(addressPointer, indices: [ IntType.int32.constant(1) ])
addressPointer = builder.buildGEP(addressPointer, type: cellTapeType, indices: [ IntType.int32.constant(1) ])
builder.currentDebugLocation = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: scope)
dibuilder.buildDbgValue(of: addressPointer, to: diVariable,
atEndOf: builder.insertBlock!,
expr: dibuilder.buildExpression([.deref]),
location: builder.currentDebugLocation!)
case "<":
// Move left
addressPointer = builder.buildGEP(addressPointer, indices: [ IntType.int32.constant(-1) ])
addressPointer = builder.buildGEP(addressPointer, type: cellTapeType, indices: [ IntType.int32.constant(-1) ])
builder.currentDebugLocation = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: scope)
dibuilder.buildDbgValue(of: addressPointer, to: diVariable,
atEndOf: builder.insertBlock!,
expr: dibuilder.buildExpression([.deref]),
location: builder.currentDebugLocation!)
case "+":
// Increment
let value = builder.buildLoad(addressPointer)
let value = builder.buildLoad(addressPointer, type: cellType)
let ptrUp = builder.buildAdd(value, cellType.constant(1))
builder.buildStore(ptrUp, to: addressPointer)
builder.currentDebugLocation = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: scope)
Expand All @@ -317,7 +317,7 @@ private func compileProgramBody(
location: builder.currentDebugLocation!)
case "-":
// Decrement
let value = builder.buildLoad(addressPointer)
let value = builder.buildLoad(addressPointer, type: cellType)
let ptrDown = builder.buildSub(value, cellType.constant(1))
builder.buildStore(ptrDown, to: addressPointer)
builder.currentDebugLocation = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: scope)
Expand All @@ -327,7 +327,7 @@ private func compileProgramBody(
location: builder.currentDebugLocation!)
case ".":
// Write
let dataValue = builder.buildLoad(addressPointer)
let dataValue = builder.buildLoad(addressPointer, type: cellType)
_ = builder.buildCall(putCharExtern, args: [dataValue])
builder.currentDebugLocation = dibuilder.buildDebugLocation(at: (sourceLine, sourceColumn), in: scope)
case ",":
Expand All @@ -343,7 +343,7 @@ private func compileProgramBody(
let loopExit = function.appendBasicBlock(named: "exit")

// If zero
let cond = builder.buildIsNotNull(builder.buildLoad(addressPointer))
let cond = builder.buildIsNotNull(builder.buildLoad(addressPointer, type: cellType))
builder.buildCondBr(condition: cond, then: loopBody, else: loopExit)

// Build a PHI for any address pointer changes in the exit block.
Expand Down Expand Up @@ -387,7 +387,7 @@ private func compileProgramBody(
loop.exitDestination.addIncoming([ (addressPointer, builder.insertBlock!) ])

// If not zero.
let cond = builder.buildIsNotNull(builder.buildLoad(addressPointer))
let cond = builder.buildIsNotNull(builder.buildLoad(addressPointer, type: cellType))
builder.buildCondBr(condition: cond, then: loop.body, else: loop.exit)

// Move the exit block after the loop body.
Expand Down
Loading

0 comments on commit b40580c

Please sign in to comment.