Skip to content

Added iteration attributes to Module, Global, and Function #31

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
Jan 14, 2017
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
12 changes: 12 additions & 0 deletions Sources/LLVM/Function.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ public class Function: IRValue {
}
}

/// Retrieves the previous function in the module, if there is one.
public func previous() -> Function? {
guard let previous = LLVMGetPreviousFunction(llvm) else { return nil }
return Function(llvm: previous)
}

/// Retrieves the next function in the module, if there is one.
public func next() -> Function? {
guard let next = LLVMGetNextFunction(llvm) else { return nil }
return Function(llvm: next)
}

/// Retrieves a parameter at the given index, if it exists.
///
/// - parameter index: The index of the parameter to retrieve.
Expand Down
12 changes: 12 additions & 0 deletions Sources/LLVM/Global.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ public struct Global: IRValue {
set { LLVMSetThreadLocal(asLLVM(), newValue.llvm) }
}

/// Retrieves the previous global in the module, if there is one.
public func previous() -> Global? {
guard let previous = LLVMGetPreviousGlobal(llvm) else { return nil }
return Global(llvm: previous)
}

/// Retrieves the next global in the module, if there is one.
public func next() -> Global? {
guard let next = LLVMGetNextGlobal(llvm) else { return nil }
return Global(llvm: next)
}

/// Deletes the global variable from its containing module.
/// - note: This does not remove references to this global from the
/// module. Ensure you have removed all insructions that reference
Expand Down
55 changes: 54 additions & 1 deletion Sources/LLVM/Module.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public enum ModuleError: Error, CustomStringConvertible {
/// A `Module` represents the top-level structure of an LLVM program. An LLVM
/// module is effectively a translation unit or a collection of translation
/// units merged together.
public final class Module {
public final class Module: CustomStringConvertible {
internal let llvm: LLVMModuleRef

/// Creates a `Module` with the given name.
Expand Down Expand Up @@ -123,11 +123,64 @@ public final class Module {
}
}

/// Retrieves the sequence of functions that make up this module.
public var functions: AnySequence<Function> {
var current = firstFunction
return AnySequence<Function> {
return AnyIterator<Function> {
defer { current = current?.next() }
return current
}
}
}

/// Retrieves the first function in this module, if there are any functions.
public var firstFunction: Function? {
guard let fn = LLVMGetFirstFunction(llvm) else { return nil }
return Function(llvm: fn)
}

/// Retrieves the last function in this module, if there are any functions.
public var lastFunction: Function? {
guard let fn = LLVMGetLastFunction(llvm) else { return nil }
return Function(llvm: fn)
}

/// Retrieves the first global in this module, if there are any globals.
public var firstGlobal: Global? {
guard let fn = LLVMGetFirstGlobal(llvm) else { return nil }
return Global(llvm: fn)
}

/// Retrieves the last global in this module, if there are any globals.
public var lastGlobal: Global? {
guard let fn = LLVMGetLastGlobal(llvm) else { return nil }
return Global(llvm: fn)
}

/// Retrieves the sequence of functions that make up this module.
public var globals: AnySequence<Global> {
var current = firstGlobal
return AnySequence<Global> {
return AnyIterator<Global> {
defer { current = current?.next() }
return current
}
}
}

/// Dump a representation of this module to stderr.
public func dump() {
LLVMDumpModule(llvm)
}

/// The full text IR of this module
public var description: String {
let cStr = LLVMPrintModuleToString(llvm)!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems... heavy for description. But I can find precedent in other bindings for this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't think of any other thing for description.
This would also allow for print(module) to print the IR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

defer { LLVMDisposeMessage(cStr) }
return String(cString: cStr)
}

deinit {
LLVMDisposeModule(llvm)
}
Expand Down