Skip to content

Commit 00b72e2

Browse files
authored
Merge pull request #59 from trill-lang/standard-procedure
C stdlib calls and FPCast
2 parents 13bb24c + 216af68 commit 00b72e2

File tree

2 files changed

+102
-4
lines changed

2 files changed

+102
-4
lines changed

Sources/LLVM/IRBuilder.swift

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -580,24 +580,32 @@ public class IRBuilder {
580580
/// value.
581581
///
582582
/// Whether an integer or floating point divide instruction is built is
583-
/// determined by the type of the first given value. Providing operands that
583+
/// determined by the type of the first given value. Providing operands that
584584
/// are neither integers nor floating values is a fatal condition.
585585
///
586586
/// - parameter lhs: The first value (the dividend).
587587
/// - parameter rhs: The second value (the divisor).
588588
/// - parameter signed: Whether to emit a signed or unsigned remainder
589-
/// instruction. Defaults to emission of a signed divide instruction.
589+
/// instruction. Defaults to emission of a signed
590+
/// divide instruction.
591+
/// - parameter exact: Whether this division must be exact. Defaults to
592+
/// inexact.
590593
/// - parameter name: The name for the newly inserted instruction.
591594
///
592595
/// - returns: A value representing the quotient of the first and second
593596
/// operands.
594597
public func buildDiv(_ lhs: IRValue, _ rhs: IRValue,
595-
signed: Bool = true, name: String = "") -> IRValue {
598+
signed: Bool = true, exact: Bool = false,
599+
name: String = "") -> IRValue {
596600
let lhsVal = lhs.asLLVM()
597601
let rhsVal = rhs.asLLVM()
598602
if lhs.type is IntType {
599603
if signed {
600-
return LLVMBuildSDiv(llvm, lhsVal, rhsVal, name)
604+
if exact {
605+
return LLVMBuildExactSDiv(llvm, lhsVal, rhsVal, name)
606+
} else {
607+
return LLVMBuildSDiv(llvm, lhsVal, rhsVal, name)
608+
}
601609
} else {
602610
return LLVMBuildUDiv(llvm, lhsVal, rhsVal, name)
603611
}
@@ -960,6 +968,30 @@ public class IRBuilder {
960968
return LLVMBuildStructGEP(llvm, ptr.asLLVM(), UInt32(index), name)
961969
}
962970

971+
/// Builds an ExtractElement instruction to retrieve an indexed value from a
972+
/// vector value.
973+
///
974+
/// - parameter vec: The vector you're indexing into.
975+
/// - parameter index: The index at which to extract.
976+
///
977+
/// - returns: The value in the vector at the provided index.
978+
public func buildExtractElement(_ vec: IRValue, index: IRValue,
979+
name: String = "") -> IRValue {
980+
return LLVMBuildExtractElement(llvm, vec.asLLVM(), index.asLLVM(), name)
981+
}
982+
983+
/// Builds an ExtractValue instruction to retrieve an indexed value from a
984+
/// struct or array value.
985+
///
986+
/// - parameter value: The struct or array you're indexing into.
987+
/// - parameter index: The index at which to extract.
988+
///
989+
/// - returns: The value in the struct at the provided index.
990+
public func buildExtractValue(_ value: IRValue, index: Int,
991+
name: String = "") -> IRValue {
992+
return LLVMBuildExtractValue(llvm, value.asLLVM(), UInt32(index), name)
993+
}
994+
963995
// MARK: Null Test Instructions
964996

965997
/// Builds a comparision instruction that returns whether the given operand is
@@ -1013,6 +1045,20 @@ public class IRBuilder {
10131045
public func buildBitCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue {
10141046
return LLVMBuildBitCast(llvm, val.asLLVM(), type.asLLVM(), name)
10151047
}
1048+
1049+
/// Builds a cast instruction to convert the given floating-point value to a
1050+
/// value of the given type.
1051+
///
1052+
/// - parameter val: The value to cast.
1053+
/// - parameter type: The destination type.
1054+
/// - parameter name: The name for the newly inserted instruction.
1055+
///
1056+
/// - returns: A value representing the result of casting the given value
1057+
/// to fit the given type.
1058+
public func buildFPCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue {
1059+
return LLVMBuildFPCast(llvm, val.asLLVM(), type.asLLVM(), name)
1060+
}
1061+
10161062
/// Builds a truncate instruction to truncate the given value to the given
10171063
/// type with a shorter width.
10181064
///
@@ -1221,6 +1267,41 @@ public class IRBuilder {
12211267
return LLVMBuildAtomicRMW(llvm, atomicOp.llvm, ptr.asLLVM(), value.asLLVM(), ordering.llvm, singleThreaded.llvm)
12221268
}
12231269

1270+
// MARK: C Standard Library Instructions
1271+
1272+
/// Builds a call to the C standard library `malloc` instruction.
1273+
/// ```
1274+
/// (type *)malloc(sizeof(type));
1275+
/// ```
1276+
/// If `count` is provided, it is equivalent to:
1277+
/// ```
1278+
/// (type *)malloc(sizeof(type) * count);
1279+
/// ```
1280+
///
1281+
/// - parameter type: The intended result type being allocated. The result
1282+
/// of the `malloc` will be a pointer to this type.
1283+
/// - parameter count: An optional number of slots to allocate, to simulate a
1284+
/// C array. This is equivalent to
1285+
/// - parameter name: The intended name for the `malloc`'d value.
1286+
public func buildMalloc(_ type: IRType, count: IRValue? = nil,
1287+
name: String = "") -> IRValue {
1288+
if let count = count {
1289+
return LLVMBuildArrayMalloc(llvm, type.asLLVM(), count.asLLVM(), name)
1290+
} else {
1291+
return LLVMBuildMalloc(llvm, type.asLLVM(), name)
1292+
}
1293+
}
1294+
1295+
/// Builds a call to the C standard library `free` function, with the provided
1296+
/// pointer.
1297+
///
1298+
/// - parameter ptr: The pointer to `free`.
1299+
/// - returns: The `free` instruction.
1300+
@discardableResult
1301+
public func buildFree(_ ptr: IRValue) -> IRValue {
1302+
return LLVMBuildFree(llvm, ptr.asLLVM())
1303+
}
1304+
12241305
// MARK: Aggregate Instructions
12251306

12261307
/// Builds an instruction to insert a value into a member field in an

Tests/LLVMTests/IRBuilderSpec.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,15 @@ class IRBuilderSpec : XCTestCase {
253253
module.dump()
254254
})
255255

256+
// MARK: Cast Instructions
257+
256258
XCTAssert(fileCheckOutput(of: .stderr, withPrefixes: ["CAST"]) {
257259
// CAST: ; ModuleID = '[[ModuleName:IRBuilderTest]]'
258260
// CAST-NEXT: source_filename = "[[ModuleName]]"
259261
let module = Module(name: "IRBuilderTest")
260262
let builder = IRBuilder(module: module)
261263

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

290+
// CAST-NEXT: %5 = alloca double
291+
let dblAlloca = builder.buildAlloca(type: FloatType.double)
292+
293+
// CAST-NEXT: %6 = load double, double* %5
294+
let dblVal = builder.buildLoad(dblAlloca)
295+
296+
// CAST-NEXT: %7 = fptrunc double %6 to float
297+
let fltVal = builder.buildFPCast(dblVal, type: FloatType.float)
298+
299+
// CAST-NEXT: %8 = fpext float %7 to double
300+
_ = builder.buildFPCast(fltVal, type: FloatType.double)
301+
287302
// CAST-NEXT: ret i32 0
288303
builder.buildRet(IntType.int32.constant(0))
289304

290305
// CAST-NEXT: }
291306
module.dump()
292307
})
308+
309+
// MARK: C Standard Library Instructions
293310
}
294311

295312
#if !os(macOS)

0 commit comments

Comments
 (0)