From d28f4384e2c4116200cbd46ec589ba98f999dde4 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Thu, 16 Feb 2017 19:09:36 -0500 Subject: [PATCH 1/3] Finish up the builder's instructions --- Sources/LLVM/IRBuilder.swift | 182 ++++++++++++++++++++++++++++++++++- 1 file changed, 181 insertions(+), 1 deletion(-) diff --git a/Sources/LLVM/IRBuilder.swift b/Sources/LLVM/IRBuilder.swift index 9f29ab49..e1fef4c2 100644 --- a/Sources/LLVM/IRBuilder.swift +++ b/Sources/LLVM/IRBuilder.swift @@ -214,6 +214,111 @@ public enum AtomicOrdering: Comparable { } } +/// `BinaryOperation` enumerates the subset of opcodes that are binary operations. +public enum BinaryOperation { + /// The `add` instruction. + case add + /// The `fadd` instruction. + case fadd + /// The `sub` instruction. + case sub + /// The `fsub` instruction. + case fsub + /// The `mul` instruction. + case mul + /// The `fmul` instruction. + case fmul + /// The `udiv` instruction. + case udiv + /// The `sdiv` instruction. + case sdiv + /// The `fdiv` instruction. + case fdiv + /// The `urem` instruction. + case urem + /// The `srem` instruction. + case srem + /// The `frem` instruction. + case frem + + /// The `shl` instruction. + case shl + /// The `lshr` instruction. + case lshr + /// The `ashr` instruction. + case ashr + /// The `and` instruction. + case and + /// The `or` instruction. + case or + /// The `xor` instruction. + case xor + + static let binaryOperationMap: [BinaryOperation: LLVMOpcode] = [ + .add: LLVMAdd, .fadd: LLVMFAdd, .sub: LLVMSub, .fsub: LLVMFSub, + .mul: LLVMMul, .fmul: LLVMFMul, .udiv: LLVMUDiv, .sdiv: LLVMSDiv, + .fdiv: LLVMFDiv, .urem: LLVMURem, .srem: LLVMSRem, .frem: LLVMFRem, + .shl: LLVMShl, .lshr: LLVMLShr, .ashr: LLVMAShr, .and: LLVMAnd, + .or: LLVMOr, .xor: LLVMXor, + ] + + /// Retrieves the corresponding `LLVMOpcode`. + public var llvm: LLVMOpcode { + return BinaryOperation.binaryOperationMap[self]! + } +} + +/// `CastOperation` enumerates the subset of opcodes that are cast operations. +public enum CastOperation { + /// The `trunc` instruction. + case trunc + /// The `zext` instruction. + case zext + /// The `sext` instruction. + case sext + /// The `fpToUI` instruction. + case fpToUI + /// The `fpToSI` instruction. + case fpToSI + /// The `uiToFP` instruction. + case uiToFP + /// The `siToFP` instruction. + case siToFP + /// The `fpTrunc` instruction. + case fpTrunc + /// The `fpext` instruction. + case fpext + /// The `ptrToInt` instruction. + case ptrToInt + /// The `intToPtr` instruction. + case intToPtr + /// The `bitCast` instruction. + case bitCast + /// The `addrSpaceCast` instruction. + case addrSpaceCast + + static let castOperationMap: [CastOperation: LLVMOpcode] = [ + .trunc: LLVMTrunc, + .zext: LLVMZExt, + .sext: LLVMSExt, + .fpToUI: LLVMFPToUI, + .fpToSI: LLVMFPToSI, + .uiToFP: LLVMUIToFP, + .siToFP: LLVMSIToFP, + .fpTrunc: LLVMFPTrunc, + .fpext: LLVMFPExt, + .ptrToInt: LLVMPtrToInt, + .intToPtr: LLVMIntToPtr, + .bitCast: LLVMBitCast, + .addrSpaceCast: LLVMAddrSpaceCast, + ] + + /// Retrieves the corresponding `LLVMOpcode`. + public var llvm: LLVMOpcode { + return CastOperation.castOperationMap[self]! + } +} + /// `AtomicReadModifyWriteOperation` enumerates the kinds of supported atomic /// read-write-modify operations. public enum AtomicReadModifyWriteOperation { @@ -421,6 +526,35 @@ public class IRBuilder { } } + // MARK: Convenience Instructions + + /// Builds the specified binary operation instruction with the given arguments. + /// + /// - parameter op: The operation to build. + /// - parameter lhs: The first operand. + /// - parameter rhs: The second operand. + /// - parameter name: The name for the newly inserted instruction. + /// + /// - returns: A value representing the result of perfomring the given binary + /// operation with the given values as arguments. + public func buildBinaryOperation(_ op: BinaryOperation, _ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue { + return LLVMBuildBinOp(llvm, op.llvm, lhs.asLLVM(), rhs.asLLVM(), name) + } + + /// Builds the specified cast operation instruction with the given value and + /// destination type. + /// + /// - parameter op: The cast operation to build. + /// - parameter value: The value to cast. + /// - parameter type: The destination type to cast to. + /// - parameter name: The name for the newly inserted instruction. + /// + /// - returns: A value representing the result of casting the given value to + /// the given destination type using the given operation. + public func buildCast(_ op: CastOperation, value: IRValue, type: IRType, name: String = "") -> IRValue { + return LLVMBuildCast(llvm, op.llvm, value.asLLVM(), type.asLLVM(), name) + } + // MARK: Arithmetic Instructions /// Builds a negation instruction with the given value as an operand. @@ -432,7 +566,7 @@ public class IRBuilder { /// - parameter value: The value to negate. /// - parameter overflowBehavior: Should overflow occur, specifies the /// behavior of the program. - /// - name: The name for the newly inserted instruction. + /// - parameter name: The name for the newly inserted instruction. /// /// - returns: A value representing the negation of the given value. public func buildNeg(_ value: IRValue, @@ -1035,6 +1169,21 @@ public class IRBuilder { public func buildResume(_ val: IRValue) -> IRValue { return LLVMBuildResume(llvm, val.asLLVM()) } + + /// Build a `va_arg` instruction to access arguments passed through the + /// "variable argument" area of a function call. + /// + /// This instruction is used to implement the `va_arg` macro in C. + /// + /// - parameter list: A value of type `va_list*` + /// - parameter type: THe type of values in the variable argument area. + /// - parameter name: The name for the newly inserted instruction. + /// + /// - returns: A value of the specified argument type. In addition, the + /// `va_list` pointer is incremented to point to the next argument. + public func buildVAArg(_ list: IRValue, type: IRType, name: String = "") -> IRValue { + return LLVMBuildVAArg(llvm, list.asLLVM(), type.asLLVM(), name) + } // MARK: Memory Access Instructions @@ -1191,6 +1340,19 @@ public class IRBuilder { return LLVMBuildTruncOrBitCast(llvm, val.asLLVM(), type.asLLVM(), name) } + /// Builds an instruction that either performs a zero extension or a bitcast of + /// the given value to a value of the given type with a wider width. + /// + /// - parameter val: The value to zero extend. + /// - parameter type: The destination type. + /// - parameter name: The name for the newly inserted instruction. + /// + /// - returns: A value representing the result of zero extending or bitcasting + /// the given value to fit the given type. + public func buildZExtOrBitCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue { + return LLVMBuildZExtOrBitCast(llvm, val.asLLVM(), type.asLLVM(), name) + } + /// Builds a bitcast instruction to convert the given value to a value of the /// given type by just copying the bit pattern. /// @@ -1552,6 +1714,24 @@ public class IRBuilder { return LLVMBuildExtractElement(llvm, vector.asLLVM(), index.asLLVM(), name) } + /// Builds a vector shuffle instruction to construct a permutation of elements + /// from the two given input vectors, returning a vector with the same element + /// type as the inputs and length that is the same as the shuffle mask. + /// + /// - parameter vector1: The first vector to shuffle. + /// - parameter vector2: The second vector to shuffle. + /// - parameter mask: A constant vector of `i32` values that acts as a mask + /// for the shuffled vectors. + /// + /// - returns: A value representing a vector with the same element type as the + /// inputs and length that is the same as the shuffle mask. + public func buildShuffleVector(_ vector1: IRValue, and vector2: IRValue, mask: IRValue, name: String = "") -> IRValue { + guard let maskTy = mask.type as? VectorType, maskTy.elementType is IntType else { + fatalError("Vector shuffle mask's elements must be 32-bit integers") + } + return LLVMBuildShuffleVector(llvm, vector1.asLLVM(), vector2.asLLVM(), mask.asLLVM(), name) + } + // MARK: Global Variable Instructions /// Build a named global of the given type. From ba02fef68d3bdfa0c2b98548fcd9a40c1e0eb80d Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Thu, 16 Feb 2017 19:13:40 -0500 Subject: [PATCH 2/3] Remove a duplicate instance of extract element --- Sources/LLVM/IRBuilder.swift | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Sources/LLVM/IRBuilder.swift b/Sources/LLVM/IRBuilder.swift index e1fef4c2..92faa3bb 100644 --- a/Sources/LLVM/IRBuilder.swift +++ b/Sources/LLVM/IRBuilder.swift @@ -1275,18 +1275,6 @@ public class IRBuilder { return LLVMBuildStructGEP(llvm, ptr.asLLVM(), UInt32(index), name) } - /// Builds an ExtractElement instruction to retrieve an indexed value from a - /// vector value. - /// - /// - parameter vec: The vector you're indexing into. - /// - parameter index: The index at which to extract. - /// - /// - returns: The value in the vector at the provided index. - public func buildExtractElement(_ vec: IRValue, index: IRValue, - name: String = "") -> IRValue { - return LLVMBuildExtractElement(llvm, vec.asLLVM(), index.asLLVM(), name) - } - /// Builds an ExtractValue instruction to retrieve an indexed value from a /// struct or array value. /// From fd9afe687de28f156a0d9c5533eda2279119fc60 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Sat, 18 Feb 2017 22:25:49 -0500 Subject: [PATCH 3/3] Add tests --- Sources/LLVM/IRBuilder.swift | 111 +----------------- Sources/LLVM/OpCode.swift | 107 +++++++++++++++++ Tests/LLVMTests/FileCheck.swift | 2 +- Tests/LLVMTests/IROperationSpec.swift | 158 ++++++++++++++++++++++++++ Tests/LinuxMain.swift | 1 + 5 files changed, 270 insertions(+), 109 deletions(-) create mode 100644 Tests/LLVMTests/IROperationSpec.swift diff --git a/Sources/LLVM/IRBuilder.swift b/Sources/LLVM/IRBuilder.swift index 92faa3bb..4c39ac16 100644 --- a/Sources/LLVM/IRBuilder.swift +++ b/Sources/LLVM/IRBuilder.swift @@ -214,111 +214,6 @@ public enum AtomicOrdering: Comparable { } } -/// `BinaryOperation` enumerates the subset of opcodes that are binary operations. -public enum BinaryOperation { - /// The `add` instruction. - case add - /// The `fadd` instruction. - case fadd - /// The `sub` instruction. - case sub - /// The `fsub` instruction. - case fsub - /// The `mul` instruction. - case mul - /// The `fmul` instruction. - case fmul - /// The `udiv` instruction. - case udiv - /// The `sdiv` instruction. - case sdiv - /// The `fdiv` instruction. - case fdiv - /// The `urem` instruction. - case urem - /// The `srem` instruction. - case srem - /// The `frem` instruction. - case frem - - /// The `shl` instruction. - case shl - /// The `lshr` instruction. - case lshr - /// The `ashr` instruction. - case ashr - /// The `and` instruction. - case and - /// The `or` instruction. - case or - /// The `xor` instruction. - case xor - - static let binaryOperationMap: [BinaryOperation: LLVMOpcode] = [ - .add: LLVMAdd, .fadd: LLVMFAdd, .sub: LLVMSub, .fsub: LLVMFSub, - .mul: LLVMMul, .fmul: LLVMFMul, .udiv: LLVMUDiv, .sdiv: LLVMSDiv, - .fdiv: LLVMFDiv, .urem: LLVMURem, .srem: LLVMSRem, .frem: LLVMFRem, - .shl: LLVMShl, .lshr: LLVMLShr, .ashr: LLVMAShr, .and: LLVMAnd, - .or: LLVMOr, .xor: LLVMXor, - ] - - /// Retrieves the corresponding `LLVMOpcode`. - public var llvm: LLVMOpcode { - return BinaryOperation.binaryOperationMap[self]! - } -} - -/// `CastOperation` enumerates the subset of opcodes that are cast operations. -public enum CastOperation { - /// The `trunc` instruction. - case trunc - /// The `zext` instruction. - case zext - /// The `sext` instruction. - case sext - /// The `fpToUI` instruction. - case fpToUI - /// The `fpToSI` instruction. - case fpToSI - /// The `uiToFP` instruction. - case uiToFP - /// The `siToFP` instruction. - case siToFP - /// The `fpTrunc` instruction. - case fpTrunc - /// The `fpext` instruction. - case fpext - /// The `ptrToInt` instruction. - case ptrToInt - /// The `intToPtr` instruction. - case intToPtr - /// The `bitCast` instruction. - case bitCast - /// The `addrSpaceCast` instruction. - case addrSpaceCast - - static let castOperationMap: [CastOperation: LLVMOpcode] = [ - .trunc: LLVMTrunc, - .zext: LLVMZExt, - .sext: LLVMSExt, - .fpToUI: LLVMFPToUI, - .fpToSI: LLVMFPToSI, - .uiToFP: LLVMUIToFP, - .siToFP: LLVMSIToFP, - .fpTrunc: LLVMFPTrunc, - .fpext: LLVMFPExt, - .ptrToInt: LLVMPtrToInt, - .intToPtr: LLVMIntToPtr, - .bitCast: LLVMBitCast, - .addrSpaceCast: LLVMAddrSpaceCast, - ] - - /// Retrieves the corresponding `LLVMOpcode`. - public var llvm: LLVMOpcode { - return CastOperation.castOperationMap[self]! - } -} - /// `AtomicReadModifyWriteOperation` enumerates the kinds of supported atomic /// read-write-modify operations. public enum AtomicReadModifyWriteOperation { @@ -537,7 +432,7 @@ public class IRBuilder { /// /// - returns: A value representing the result of perfomring the given binary /// operation with the given values as arguments. - public func buildBinaryOperation(_ op: BinaryOperation, _ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue { + public func buildBinaryOperation(_ op: OpCode.Binary, _ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue { return LLVMBuildBinOp(llvm, op.llvm, lhs.asLLVM(), rhs.asLLVM(), name) } @@ -551,7 +446,7 @@ public class IRBuilder { /// /// - returns: A value representing the result of casting the given value to /// the given destination type using the given operation. - public func buildCast(_ op: CastOperation, value: IRValue, type: IRType, name: String = "") -> IRValue { + public func buildCast(_ op: OpCode.Cast, value: IRValue, type: IRType, name: String = "") -> IRValue { return LLVMBuildCast(llvm, op.llvm, value.asLLVM(), type.asLLVM(), name) } @@ -1176,7 +1071,7 @@ public class IRBuilder { /// This instruction is used to implement the `va_arg` macro in C. /// /// - parameter list: A value of type `va_list*` - /// - parameter type: THe type of values in the variable argument area. + /// - parameter type: The type of values in the variable argument area. /// - parameter name: The name for the newly inserted instruction. /// /// - returns: A value of the specified argument type. In addition, the diff --git a/Sources/LLVM/OpCode.swift b/Sources/LLVM/OpCode.swift index f4cce8ec..5e70ff5f 100644 --- a/Sources/LLVM/OpCode.swift +++ b/Sources/LLVM/OpCode.swift @@ -227,3 +227,110 @@ public enum OpCode { } } } + +extension OpCode { + /// `BinaryOperation` enumerates the subset of opcodes that are binary operations. + public enum Binary { + /// The `add` instruction. + case add + /// The `fadd` instruction. + case fadd + /// The `sub` instruction. + case sub + /// The `fsub` instruction. + case fsub + /// The `mul` instruction. + case mul + /// The `fmul` instruction. + case fmul + /// The `udiv` instruction. + case udiv + /// The `sdiv` instruction. + case sdiv + /// The `fdiv` instruction. + case fdiv + /// The `urem` instruction. + case urem + /// The `srem` instruction. + case srem + /// The `frem` instruction. + case frem + + /// The `shl` instruction. + case shl + /// The `lshr` instruction. + case lshr + /// The `ashr` instruction. + case ashr + /// The `and` instruction. + case and + /// The `or` instruction. + case or + /// The `xor` instruction. + case xor + + static let binaryOperationMap: [Binary: LLVMOpcode] = [ + .add: LLVMAdd, .fadd: LLVMFAdd, .sub: LLVMSub, .fsub: LLVMFSub, + .mul: LLVMMul, .fmul: LLVMFMul, .udiv: LLVMUDiv, .sdiv: LLVMSDiv, + .fdiv: LLVMFDiv, .urem: LLVMURem, .srem: LLVMSRem, .frem: LLVMFRem, + .shl: LLVMShl, .lshr: LLVMLShr, .ashr: LLVMAShr, .and: LLVMAnd, + .or: LLVMOr, .xor: LLVMXor, + ] + + /// Retrieves the corresponding `LLVMOpcode`. + public var llvm: LLVMOpcode { + return Binary.binaryOperationMap[self]! + } + } + + /// `CastOperation` enumerates the subset of opcodes that are cast operations. + public enum Cast { + /// The `trunc` instruction. + case trunc + /// The `zext` instruction. + case zext + /// The `sext` instruction. + case sext + /// The `fpToUI` instruction. + case fpToUI + /// The `fpToSI` instruction. + case fpToSI + /// The `uiToFP` instruction. + case uiToFP + /// The `siToFP` instruction. + case siToFP + /// The `fpTrunc` instruction. + case fpTrunc + /// The `fpext` instruction. + case fpext + /// The `ptrToInt` instruction. + case ptrToInt + /// The `intToPtr` instruction. + case intToPtr + /// The `bitCast` instruction. + case bitCast + /// The `addrSpaceCast` instruction. + case addrSpaceCast + + static let castOperationMap: [Cast: LLVMOpcode] = [ + .trunc: LLVMTrunc, + .zext: LLVMZExt, + .sext: LLVMSExt, + .fpToUI: LLVMFPToUI, + .fpToSI: LLVMFPToSI, + .uiToFP: LLVMUIToFP, + .siToFP: LLVMSIToFP, + .fpTrunc: LLVMFPTrunc, + .fpext: LLVMFPExt, + .ptrToInt: LLVMPtrToInt, + .intToPtr: LLVMIntToPtr, + .bitCast: LLVMBitCast, + .addrSpaceCast: LLVMAddrSpaceCast, + ] + + /// Retrieves the corresponding `LLVMOpcode`. + public var llvm: LLVMOpcode { + return Cast.castOperationMap[self]! + } + } +} diff --git a/Tests/LLVMTests/FileCheck.swift b/Tests/LLVMTests/FileCheck.swift index 09ba0023..c57a5631 100644 --- a/Tests/LLVMTests/FileCheck.swift +++ b/Tests/LLVMTests/FileCheck.swift @@ -1167,7 +1167,7 @@ private struct CheckString { } // Re-calc it as the offset relative to the start of the original string. - var matchPos = range.location + startPos + let matchPos = range.location + startPos if !notStrings.isEmpty { if matchPos < lastPos { // Reordered? diff --git a/Tests/LLVMTests/IROperationSpec.swift b/Tests/LLVMTests/IROperationSpec.swift new file mode 100644 index 00000000..749d87d6 --- /dev/null +++ b/Tests/LLVMTests/IROperationSpec.swift @@ -0,0 +1,158 @@ +import LLVM +import XCTest +import Foundation + +class IROperationSpec : XCTestCase { + func testBinaryOps() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["BINARYOP"]) { + // BINARYOP: ; ModuleID = '[[ModuleName:BinaryOpTest]]' + // BINARYOP-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "BinaryOpTest") + let builder = IRBuilder(module: module) + + // BINARYOP: @a = global i32 1 + var gi1 = builder.addGlobal("a", type: IntType.int32) + gi1.initializer = Int32(1) + // BINARYOP-NEXT: @b = global i32 1 + var gi2 = builder.addGlobal("b", type: IntType.int32) + gi2.initializer = Int32(1) + + // BINARYOP-NEXT: @c = global float 0.000000e+00 + var gf1 = builder.addGlobal("c", type: FloatType.float) + gf1.initializer = FloatType.float.constant(0.0) + // BINARYOP-NEXT: @d = global float 0.000000e+00 + var gf2 = builder.addGlobal("d", type: FloatType.float) + gf2.initializer = FloatType.float.constant(0.0) + + // BINARYOP: define void @main() { + let main = builder.addFunction("main", + type: FunctionType(argTypes: [], + returnType: VoidType())) + // BINARYOP-NEXT: entry: + let entry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + + // BINARYOP-NEXT: %0 = load i32, i32* @a + let vgi1 = builder.buildLoad(gi1) + // BINARYOP-NEXT: %1 = load i32, i32* @b + let vgi2 = builder.buildLoad(gi2) + + // BINARYOP-NEXT: %2 = load float, float* @c + let vgf1 = builder.buildLoad(gf1) + // BINARYOP-NEXT: %3 = load float, float* @d + let vgf2 = builder.buildLoad(gf2) + + // BINARYOP-NEXT: %4 = add i32 %0, %1 + _ = builder.buildBinaryOperation(.add, vgi1, vgi2) + // BINARYOP-NEXT: %5 = sub i32 %0, %1 + _ = builder.buildBinaryOperation(.sub, vgi1, vgi2) + // BINARYOP-NEXT: %6 = mul i32 %0, %1 + _ = builder.buildBinaryOperation(.mul, vgi1, vgi2) + // BINARYOP-NEXT: %7 = udiv i32 %0, %1 + _ = builder.buildBinaryOperation(.udiv, vgi1, vgi2) + // BINARYOP-NEXT: %8 = sdiv i32 %0, %1 + _ = builder.buildBinaryOperation(.sdiv, vgi1, vgi2) + // BINARYOP-NEXT: %9 = urem i32 %0, %1 + _ = builder.buildBinaryOperation(.urem, vgi1, vgi2) + // BINARYOP-NEXT: %10 = srem i32 %0, %1 + _ = builder.buildBinaryOperation(.srem, vgi1, vgi2) + // BINARYOP-NEXT: %11 = shl i32 %0, %1 + _ = builder.buildBinaryOperation(.shl, vgi1, vgi2) + // BINARYOP-NEXT: %12 = lshr i32 %0, %1 + _ = builder.buildBinaryOperation(.lshr, vgi1, vgi2) + // BINARYOP-NEXT: %13 = ashr i32 %0, %1 + _ = builder.buildBinaryOperation(.ashr, vgi1, vgi2) + // BINARYOP-NEXT: %14 = and i32 %0, %1 + _ = builder.buildBinaryOperation(.and, vgi1, vgi2) + // BINARYOP-NEXT: %15 = or i32 %0, %1 + _ = builder.buildBinaryOperation(.or, vgi1, vgi2) + // BINARYOP-NEXT: %16 = xor i32 %0, %1 + _ = builder.buildBinaryOperation(.xor, vgi1, vgi2) + + // BINARYOP-NEXT: %17 = fadd float %2, %3 + _ = builder.buildBinaryOperation(.fadd, vgf1, vgf2) + // BINARYOP-NEXT: %18 = fsub float %2, %3 + _ = builder.buildBinaryOperation(.fsub, vgf1, vgf2) + // BINARYOP-NEXT: %19 = fmul float %2, %3 + _ = builder.buildBinaryOperation(.fmul, vgf1, vgf2) + // BINARYOP-NEXT: %20 = fdiv float %2, %3 + _ = builder.buildBinaryOperation(.fdiv, vgf1, vgf2) + // BINARYOP-NEXT: %21 = frem float %2, %3 + _ = builder.buildBinaryOperation(.frem, vgf1, vgf2) + + // BINARYOP-NEXT: ret void + builder.buildRetVoid() + // BINARYOP-NEXT: } + module.dump() + }) + } + + func testCastOps() { + XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["CASTOP"]) { + // CASTOP: ; ModuleID = '[[ModuleName:CastOpTest]]' + // CASTOP-NEXT: source_filename = "[[ModuleName]]" + let module = Module(name: "CastOpTest") + let builder = IRBuilder(module: module) + + // CASTOP: @a = global i32 1 + var gi = builder.addGlobal("a", type: IntType.int32) + gi.initializer = Int32(1) + + // CASTOP-NEXT: @f = global float 0.000000e+00 + var gf = builder.addGlobal("f", type: FloatType.float) + gf.initializer = FloatType.float.constant(0.0) + + // CASTOP: define void @main() { + let main = builder.addFunction("main", + type: FunctionType(argTypes: [], + returnType: VoidType())) + // CASTOP-NEXT: entry: + let entry = main.appendBasicBlock(named: "entry") + builder.positionAtEnd(of: entry) + + // CASTOP-NEXT: %0 = load i32, i32* @a + let vgi = builder.buildLoad(gi) + // CASTOP-NEXT: %1 = load float, float* @f + let vgf = builder.buildLoad(gf) + + // CASTOP-NEXT: %2 = trunc i32 %0 to i16 + _ = builder.buildCast(.trunc, value: vgi, type: IntType.int16) + // CASTOP-NEXT: %3 = zext i32 %0 to i64 + _ = builder.buildCast(.zext, value: vgi, type: IntType.int64) + // CASTOP-NEXT: %4 = sext i32 %0 to i64 + _ = builder.buildCast(.sext, value: vgi, type: IntType.int64) + // CASTOP-NEXT: %5 = fptoui float %1 to i32 + _ = builder.buildCast(.fpToUI, value: vgf, type: IntType.int32) + // CASTOP-NEXT: %6 = fptosi float %1 to i32 + _ = builder.buildCast(.fpToSI, value: vgf, type: IntType.int32) + // CASTOP-NEXT: %7 = uitofp i32 %0 to double + _ = builder.buildCast(.uiToFP, value: vgi, type: FloatType.double) + // CASTOP-NEXT: %8 = sitofp i32 %0 to float + _ = builder.buildCast(.siToFP, value: vgi, type: FloatType.float) + // CASTOP-NEXT: %9 = fptrunc float %1 to half + _ = builder.buildCast(.fpTrunc, value: vgf, type: FloatType.half) + // CASTOP-NEXT: %10 = fpext float %1 to fp128 + _ = builder.buildCast(.fpext, value: vgf, type: FloatType.fp128) + // CASTOP-NEXT: %11 = inttoptr i32 %0 to i32* + _ = builder.buildCast(.intToPtr, value: vgi, type: PointerType(pointee: IntType.int32)) + // CASTOP-NEXT: %12 = bitcast i32 %0 to float + _ = builder.buildCast(.bitCast, value: vgi, type: FloatType.float) + + // FIXME: These are not correct + // _ = builder.buildCast(.ptrToInt, value: gi, type: IntType.int32) + // _ = builder.buildCast(.addrSpaceCast, value: gi, type: PointerType(pointee: IntType.int32, addressSpace: 1)) + + // CASTOP-NEXT: ret void + builder.buildRetVoid() + // CASTOP-NEXT: } + module.dump() + }) + } + + #if !os(macOS) + static var allTests = testCase([ + ("testBinaryOps", testBinaryOps), + ("testCastOps", testCastOps), + ]) + #endif +} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index c9329605..0c8037d7 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -7,5 +7,6 @@ XCTMain([ IRBuilderSpec.allTests, ConstantSpec.allTests, IRExceptionSpec.allTests, + IROperationSpec.allTests, ]) #endif