From f26bf7e466021dc8b9e6fd79659ab513cb9b9b4d Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Wed, 11 Jan 2017 13:32:17 -0500 Subject: [PATCH] Added custom iterators for instructions, basic blocks, and uses of instructions. Also split Instruction and OpCode into separate files --- Sources/LLVM/BasicBlock.swift | 213 ++------------------------------- Sources/LLVM/Function.swift | 12 +- Sources/LLVM/Instruction.swift | 51 ++++++++ Sources/LLVM/OpCode.swift | 159 ++++++++++++++++++++++++ Sources/LLVM/Use.swift | 4 +- 5 files changed, 230 insertions(+), 209 deletions(-) create mode 100644 Sources/LLVM/Instruction.swift create mode 100644 Sources/LLVM/OpCode.swift diff --git a/Sources/LLVM/BasicBlock.swift b/Sources/LLVM/BasicBlock.swift index 613eaa11..e035e1a0 100644 --- a/Sources/LLVM/BasicBlock.swift +++ b/Sources/LLVM/BasicBlock.swift @@ -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. @@ -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 { + var current = firstInstruction + return AnySequence { + return AnyIterator { + 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 @@ -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 { - 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) - } -} - diff --git a/Sources/LLVM/Function.swift b/Sources/LLVM/Function.swift index 0e4cbe62..1db09ff1 100644 --- a/Sources/LLVM/Function.swift +++ b/Sources/LLVM/Function.swift @@ -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 { var current = firstBlock - while let block = current { - blocks.append(block) - current = block.next() + return AnySequence { + return AnyIterator { + defer { current = current?.next() } + return current + } } - return blocks } /// Retrieves a parameter at the given index, if it exists. diff --git a/Sources/LLVM/Instruction.swift b/Sources/LLVM/Instruction.swift new file mode 100644 index 00000000..6e77a7e2 --- /dev/null +++ b/Sources/LLVM/Instruction.swift @@ -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 { + var current = firstUse + return AnySequence { + return AnyIterator { + defer { current = current?.next() } + return current + } + } + } +} diff --git a/Sources/LLVM/OpCode.swift b/Sources/LLVM/OpCode.swift new file mode 100644 index 00000000..60c84aaf --- /dev/null +++ b/Sources/LLVM/OpCode.swift @@ -0,0 +1,159 @@ +import cllvm + +/// 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 +} diff --git a/Sources/LLVM/Use.swift b/Sources/LLVM/Use.swift index 81692519..c92884f2 100644 --- a/Sources/LLVM/Use.swift +++ b/Sources/LLVM/Use.swift @@ -11,12 +11,12 @@ public struct Use { return Use(llvm: next) } - /// Obtain the user value for this `User` object. + /// Obtain the user value for this `Use` object. public func user() -> IRValue? { return LLVMGetUser(llvm) } - /// Obtain the value this `User` object corresponds to. + /// Obtain the value this `Use` object corresponds to. public func usedValue() -> IRValue? { return LLVMGetUsedValue(llvm) }