Skip to content
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
213 changes: 12 additions & 201 deletions Sources/LLVM/BasicBlock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import cllvm
/// have predecessor basic blocks (i.e. there can not be any branches to the
/// entry block of a function). Because the block can have no predecessors, it
/// also cannot have any PHI nodes.
public struct BasicBlock: IRValue, Sequence {
public struct BasicBlock: IRValue {
internal let llvm: LLVMBasicBlockRef

/// Creates a `BasicBlock` from an `LLVMBasicBlockRef` object.
Expand Down Expand Up @@ -50,6 +50,17 @@ public struct BasicBlock: IRValue, Sequence {
return BasicBlock(llvm: blockRef)
}

/// Returns a sequence of the Instructions that make up this basic block.
public var instructions: AnySequence<Instruction> {
Copy link
Member

Choose a reason for hiding this comment

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

Translating the old docs:

/// Returns a sequence of the Instructions that make up this basic block.

var current = firstInstruction
return AnySequence<Instruction> {
return AnyIterator<Instruction> {
defer { current = current?.next() }
return current
}
}
}

/// Deletes the basic block from its containing function.
/// - note: This does not remove breaks to this block from the
/// function. Ensure you have removed all insructions that reference
Expand All @@ -72,204 +83,4 @@ public struct BasicBlock: IRValue, Sequence {
public func moveAfter(_ block: BasicBlock) {
LLVMMoveBasicBlockAfter(llvm, block.llvm)
}

/// Returns an iterator over the `Instruction`s that make up this basic block.
public func makeIterator() -> AnyIterator<Instruction> {
var current = firstInstruction
return AnyIterator {
defer { current = current?.next() }
return current
}
}
}

/// Enumerates the opcodes of instructions available in the LLVM IR language.
///
/// The raw values of this enumeration *must* match those in
/// [llvm-c/Core.h](https://github.com/llvm-mirror/llvm/blob/master/include/llvm-c/Core.h).
public enum OpCode: UInt32 {
// MARK: Terminator Instructions

// The opcode for the `ret` instruction.
case ret = 1
// The opcode for the `br` instruction.
case br = 2
// The opcode for the `switch` instruction.
case `switch` = 3
// The opcode for the `indirectBr` instruction.
case indirectBr = 4
// The opcode for the `invoke` instruction.
case invoke = 5
// The opcode for the `unreachable` instruction.
case unreachable = 7

// MARK: Standard Binary Operators

// The opcode for the `add` instruction.
case add = 8
// The opcode for the `fadd` instruction.
case fadd = 9
// The opcode for the `sub` instruction.
case sub = 10
// The opcode for the `fsub` instruction.
case fsub = 11
// The opcode for the `mul` instruction.
case mul = 12
// The opcode for the `fmul` instruction.
case fmul = 13
// The opcode for the `udiv` instruction.
case udiv = 14
// The opcode for the `sdiv` instruction.
case sdiv = 15
// The opcode for the `fdiv` instruction.
case fdiv = 16
// The opcode for the `urem` instruction.
case urem = 17
// The opcode for the `srem` instruction.
case srem = 18
// The opcode for the `frem` instruction.
case frem = 19

// MARK: Logical Operators

// The opcode for the `shl` instruction.
case shl = 20
// The opcode for the `lshr` instruction.
case lshr = 21
// The opcode for the `ashr` instruction.
case ashr = 22
// The opcode for the `and` instruction.
case and = 23
// The opcode for the `or` instruction.
case or = 24
// The opcode for the `xor` instruction.
case xor = 25

// MARK: Memory Operators

// The opcode for the `alloca` instruction.
case alloca = 26
// The opcode for the `load` instruction.
case load = 27
// The opcode for the `store` instruction.
case store = 28
// The opcode for the `getElementPtr` instruction.
case getElementPtr = 29

// MARK: Cast Operators

// The opcode for the `trunc` instruction.
case trunc = 30
// The opcode for the `zext` instruction.
case zext = 31
// The opcode for the `sext` instruction.
case sext = 32
// The opcode for the `fpToUI` instruction.
case fpToUI = 33
// The opcode for the `fpToSI` instruction.
case fpToSI = 34
// The opcode for the `uiToFP` instruction.
case uiToFP = 35
// The opcode for the `siToFP` instruction.
case siToFP = 36
// The opcode for the `fpTrunc` instruction.
case fpTrunc = 37
// The opcode for the `fpExt` instruction.
case fpExt = 38
// The opcode for the `ptrToInt` instruction.
case ptrToInt = 39
// The opcode for the `intToPtr` instruction.
case intToPtr = 40
// The opcode for the `bitCast` instruction.
case bitCast = 41
// The opcode for the `addrSpaceCast` instruction.
case addrSpaceCast = 60

// MARK: Other Operators

// The opcode for the `icmp` instruction.
case icmp = 42
// The opcode for the `fcmp` instruction.
case fcmp = 43
// The opcode for the `PHI` instruction.
case PHI = 44
// The opcode for the `call` instruction.
case call = 45
// The opcode for the `select` instruction.
case select = 46
// The opcode for the `userOp1` instruction.
case userOp1 = 47
// The opcode for the `userOp2` instruction.
case userOp2 = 48
// The opcode for the `vaArg` instruction.
case vaArg = 49
// The opcode for the `extractElement` instruction.
case extractElement = 50
// The opcode for the `insertElement` instruction.
case insertElement = 51
// The opcode for the `shuffleVector` instruction.
case shuffleVector = 52
// The opcode for the `extractValue` instruction.
case extractValue = 53
// The opcode for the `insertValue` instruction.
case insertValue = 54

// MARK: Atomic operators

// The opcode for the `fence` instruction.
case fence = 55
// The opcode for the `atomicCmpXchg` instruction.
case atomicCmpXchg = 56
// The opcode for the `atomicRMW` instruction.
case atomicRMW = 57

// MARK: Exception Handling Operators

// The opcode for the `resume` instruction.
case resume = 58
// The opcode for the `landingPad` instruction.
case landingPad = 59
// The opcode for the `cleanupRet` instruction.
case cleanupRet = 61
// The opcode for the `catchRet` instruction.
case catchRet = 62
// The opcode for the `catchPad` instruction.
case catchPad = 63
// The opcode for the `cleanupPad` instruction.
case cleanupPad = 64
// The opcode for the `catchSwitch` instruction.
case catchSwitch = 65
}

/// An `Instruction` represents an instruction residing in a basic block.
public struct Instruction: IRValue {
internal let llvm: LLVMValueRef

/// Creates an `Intruction` from an `LLVMValueRef` object.
public init(llvm: LLVMValueRef) {
self.llvm = llvm
}

/// Retrieves the underlying LLVM value object.
public func asLLVM() -> LLVMValueRef {
return llvm
}

/// Retrieves the opcode associated with this `Instruction`.
public var opCode: OpCode {
return OpCode(rawValue: LLVMGetInstructionOpcode(llvm).rawValue)!
}

/// Obtain the instruction that occurs before this one, if it exists.
public func previous() -> Instruction? {
guard let val = LLVMGetPreviousInstruction(llvm) else { return nil }
return Instruction(llvm: val)
}

/// Obtain the instruction that occurs after this one, if it exists.
public func next() -> Instruction? {
guard let val = LLVMGetNextInstruction(llvm) else { return nil }
return Instruction(llvm: val)
}
}

12 changes: 6 additions & 6 deletions Sources/LLVM/Function.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ public class Function: IRValue {
}

/// Retrieves the sequence of basic blocks that make up this function's body.
public var basicBlocks: [BasicBlock] {
var blocks = [BasicBlock]()
public var basicBlocks: AnySequence<BasicBlock> {
var current = firstBlock
while let block = current {
blocks.append(block)
current = block.next()
return AnySequence<BasicBlock> {
return AnyIterator<BasicBlock> {
defer { current = current?.next() }
return current
}
}
return blocks
}

/// Retrieves a parameter at the given index, if it exists.
Expand Down
51 changes: 51 additions & 0 deletions Sources/LLVM/Instruction.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import cllvm

/// An `Instruction` represents an instruction residing in a basic block.
public struct Instruction: IRValue {
internal let llvm: LLVMValueRef

/// Creates an `Intruction` from an `LLVMValueRef` object.
public init(llvm: LLVMValueRef) {
self.llvm = llvm
}

/// Retrieves the underlying LLVM value object.
public func asLLVM() -> LLVMValueRef {
return llvm
}

/// Retrieves the opcode associated with this `Instruction`.
public var opCode: OpCode {
return OpCode(rawValue: LLVMGetInstructionOpcode(llvm).rawValue)!
}

/// Obtain the instruction that occurs before this one, if it exists.
public func previous() -> Instruction? {
guard let val = LLVMGetPreviousInstruction(llvm) else { return nil }
return Instruction(llvm: val)
}

/// Obtain the instruction that occurs after this one, if it exists.
public func next() -> Instruction? {
guard let val = LLVMGetNextInstruction(llvm) else { return nil }
return Instruction(llvm: val)
}

public var firstUse: Use? {
guard let use = LLVMGetFirstUse(llvm) else { return nil }
return Use(llvm: use)
}


/// Retrieves the sequence of instructions that use the value from this
/// instruction.
public var uses: AnySequence<Use> {
var current = firstUse
return AnySequence<Use> {
return AnyIterator<Use> {
defer { current = current?.next() }
return current
}
}
}
}
Loading