Skip to content

Opaque Pointer Cleanup #211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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