Skip to content

C stdlib calls and FPCast #59

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 3 commits into from
Feb 2, 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
89 changes: 85 additions & 4 deletions Sources/LLVM/IRBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -580,24 +580,32 @@ public class IRBuilder {
/// value.
///
/// Whether an integer or floating point divide instruction is built is
/// determined by the type of the first given value. Providing operands that
/// determined by the type of the first given value. Providing operands that
/// are neither integers nor floating values is a fatal condition.
///
/// - parameter lhs: The first value (the dividend).
/// - parameter rhs: The second value (the divisor).
/// - parameter signed: Whether to emit a signed or unsigned remainder
/// instruction. Defaults to emission of a signed divide instruction.
/// instruction. Defaults to emission of a signed
/// divide instruction.
/// - parameter exact: Whether this division must be exact. Defaults to
/// inexact.
/// - parameter name: The name for the newly inserted instruction.
///
/// - returns: A value representing the quotient of the first and second
/// operands.
public func buildDiv(_ lhs: IRValue, _ rhs: IRValue,
signed: Bool = true, name: String = "") -> IRValue {
signed: Bool = true, exact: Bool = false,
name: String = "") -> IRValue {
let lhsVal = lhs.asLLVM()
let rhsVal = rhs.asLLVM()
if lhs.type is IntType {
if signed {
return LLVMBuildSDiv(llvm, lhsVal, rhsVal, name)
if exact {
return LLVMBuildExactSDiv(llvm, lhsVal, rhsVal, name)
} else {
return LLVMBuildSDiv(llvm, lhsVal, rhsVal, name)
}
} else {
return LLVMBuildUDiv(llvm, lhsVal, rhsVal, name)
}
Expand Down Expand Up @@ -960,6 +968,30 @@ 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.
///
/// - parameter value: The struct or array you're indexing into.
/// - parameter index: The index at which to extract.
///
/// - returns: The value in the struct at the provided index.
public func buildExtractValue(_ value: IRValue, index: Int,
name: String = "") -> IRValue {
return LLVMBuildExtractValue(llvm, value.asLLVM(), UInt32(index), name)
}

// MARK: Null Test Instructions

/// Builds a comparision instruction that returns whether the given operand is
Expand Down Expand Up @@ -1013,6 +1045,20 @@ public class IRBuilder {
public func buildBitCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue {
return LLVMBuildBitCast(llvm, val.asLLVM(), type.asLLVM(), name)
}

/// Builds a cast instruction to convert the given floating-point value to a
/// value of the given type.
///
/// - parameter val: The value to cast.
/// - parameter type: The destination type.
/// - parameter name: The name for the newly inserted instruction.
///
/// - returns: A value representing the result of casting the given value
/// to fit the given type.
public func buildFPCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue {
return LLVMBuildFPCast(llvm, val.asLLVM(), type.asLLVM(), name)
}

/// Builds a truncate instruction to truncate the given value to the given
/// type with a shorter width.
///
Expand Down Expand Up @@ -1221,6 +1267,41 @@ public class IRBuilder {
return LLVMBuildAtomicRMW(llvm, atomicOp.llvm, ptr.asLLVM(), value.asLLVM(), ordering.llvm, singleThreaded.llvm)
}

// MARK: C Standard Library Instructions

/// Builds a call to the C standard library `malloc` instruction.
/// ```
/// (type *)malloc(sizeof(type));
/// ```
/// If `count` is provided, it is equivalent to:
/// ```
/// (type *)malloc(sizeof(type) * count);
/// ```
///
/// - parameter type: The intended result type being allocated. The result
/// of the `malloc` will be a pointer to this type.
/// - parameter count: An optional number of slots to allocate, to simulate a
/// C array. This is equivalent to
/// - parameter name: The intended name for the `malloc`'d value.
public func buildMalloc(_ type: IRType, count: IRValue? = nil,
name: String = "") -> IRValue {
if let count = count {
return LLVMBuildArrayMalloc(llvm, type.asLLVM(), count.asLLVM(), name)
} else {
return LLVMBuildMalloc(llvm, type.asLLVM(), name)
}
}

/// Builds a call to the C standard library `free` function, with the provided
/// pointer.
///
/// - parameter ptr: The pointer to `free`.
/// - returns: The `free` instruction.
@discardableResult
public func buildFree(_ ptr: IRValue) -> IRValue {
return LLVMBuildFree(llvm, ptr.asLLVM())
}

// MARK: Aggregate Instructions

/// Builds an instruction to insert a value into a member field in an
Expand Down
17 changes: 17 additions & 0 deletions Tests/LLVMTests/IRBuilderSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,15 @@ class IRBuilderSpec : XCTestCase {
module.dump()
})

// MARK: Cast Instructions

XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["CAST"]) {
// CAST: ; ModuleID = '[[ModuleName:IRBuilderTest]]'
// CAST-NEXT: source_filename = "[[ModuleName]]"
let module = Module(name: "IRBuilderTest")
let builder = IRBuilder(module: module)


// CAST: define i32 @main() {
let main = builder.addFunction("main",
type: FunctionType(argTypes: [],
Expand All @@ -284,12 +287,26 @@ class IRBuilderSpec : XCTestCase {
// CAST-NEXT: %4 = bitcast i64* %0 to i8*
_ = builder.buildBitCast(alloca, type: PointerType.toVoid)

// CAST-NEXT: %5 = alloca double
let dblAlloca = builder.buildAlloca(type: FloatType.double)

// CAST-NEXT: %6 = load double, double* %5
let dblVal = builder.buildLoad(dblAlloca)

// CAST-NEXT: %7 = fptrunc double %6 to float
let fltVal = builder.buildFPCast(dblVal, type: FloatType.float)

// CAST-NEXT: %8 = fpext float %7 to double
_ = builder.buildFPCast(fltVal, type: FloatType.double)

// CAST-NEXT: ret i32 0
builder.buildRet(IntType.int32.constant(0))

// CAST-NEXT: }
module.dump()
})

// MARK: C Standard Library Instructions
}

#if !os(macOS)
Expand Down