Skip to content

Commit 66a0be4

Browse files
authored
Merge pull request #75 from CodaFi/cold-calling
Model Call and Invoke as higher-level structures
2 parents 5f9d0bf + 468303d commit 66a0be4

File tree

2 files changed

+70
-4
lines changed

2 files changed

+70
-4
lines changed

Sources/LLVM/Call.swift

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#if !NO_SWIFTPM
2+
import cllvm
3+
#endif
4+
5+
/// Represents a simple function call.
6+
public struct Call: IRValue {
7+
let llvm: LLVMValueRef
8+
9+
/// Retrieves the underlying LLVM value object.
10+
public func asLLVM() -> LLVMValueRef {
11+
return self.llvm
12+
}
13+
14+
/// Retrieves the number of argument operands passed by this call.
15+
public var argumentCount: Int {
16+
return Int(LLVMGetNumArgOperands(self.llvm))
17+
}
18+
19+
/// Accesses the calling convention for this function call.
20+
public var callingConvention: CallingConvention {
21+
get { return CallingConvention(rawValue: LLVMGetInstructionCallConv(self.llvm))! }
22+
set { LLVMSetInstructionCallConv(self.llvm, newValue.rawValue) }
23+
}
24+
25+
/// Returns whether this function call is a tail call. That is, if the callee
26+
/// may reuse the stack memory of the caller.
27+
///
28+
/// This attribute requires support from the target architecture.
29+
public var isTailCall: Bool {
30+
get { return LLVMIsTailCall(self.llvm) != 0 }
31+
set { LLVMSetTailCall(self.llvm, newValue.llvm) }
32+
}
33+
34+
/// Retrieves the alignment of the parameter at the given index.
35+
///
36+
/// This property is currently set-only due to limitations of the LLVM C API.
37+
///
38+
/// - parameter i: The index of the parameter to retrieve.
39+
/// - parameter alignment: The alignment to apply to the parameter.
40+
public func setParameterAlignment(at i : Int, to alignment: Int) {
41+
LLVMSetInstrParamAlignment(self.llvm, UInt32(i), UInt32(alignment))
42+
}
43+
}
44+
45+
/// Represents a function call that may transfer control to an exception handler.
46+
public struct Invoke: IRValue {
47+
let llvm: LLVMValueRef
48+
49+
/// Retrieves the underlying LLVM value object.
50+
public func asLLVM() -> LLVMValueRef {
51+
return self.llvm
52+
}
53+
54+
/// Accesses the destination block the flow of control will transfer to if an
55+
/// exception does not occur.
56+
public var normalDestination: BasicBlock {
57+
get { return BasicBlock(llvm: LLVMGetNormalDest(self.llvm)) }
58+
set { LLVMSetNormalDest(self.llvm, newValue.asLLVM()) }
59+
}
60+
61+
/// Accesses the destination block that exception unwinding will jump to.
62+
public var unwindDestination: BasicBlock {
63+
get { return BasicBlock(llvm: LLVMGetUnwindDest(self.llvm)) }
64+
set { LLVMSetUnwindDest(self.llvm, newValue.asLLVM()) }
65+
}
66+
}

Sources/LLVM/IRBuilder.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -965,10 +965,10 @@ public class IRBuilder {
965965
/// - parameter name: The name for the newly inserted instruction.
966966
///
967967
/// - returns: A value representing the result of returning from the callee.
968-
public func buildCall(_ fn: IRValue, args: [IRValue], name: String = "") -> IRValue {
968+
public func buildCall(_ fn: IRValue, args: [IRValue], name: String = "") -> Call {
969969
var args = args.map { $0.asLLVM() as Optional }
970970
return args.withUnsafeMutableBufferPointer { buf in
971-
return LLVMBuildCall(llvm, fn.asLLVM(), buf.baseAddress!, UInt32(buf.count), name)
971+
return Call(llvm: LLVMBuildCall(llvm, fn.asLLVM(), buf.baseAddress!, UInt32(buf.count), name))
972972
}
973973
}
974974

@@ -994,12 +994,12 @@ public class IRBuilder {
994994
/// - returns: A value representing the result of returning from the callee
995995
/// under normal circumstances. Under exceptional circumstances, the value
996996
/// represents the value of any `resume` instruction in the `catch` block.
997-
public func buildInvoke(_ fn: IRValue, args: [IRValue], next: BasicBlock, catch: BasicBlock, name: String = "") -> IRValue {
997+
public func buildInvoke(_ fn: IRValue, args: [IRValue], next: BasicBlock, catch: BasicBlock, name: String = "") -> Invoke {
998998
precondition(`catch`.firstInstruction!.opCode == .landingPad, "First instruction of catch block must be a landing pad")
999999

10001000
var args = args.map { $0.asLLVM() as Optional }
10011001
return args.withUnsafeMutableBufferPointer { buf in
1002-
return LLVMBuildInvoke(llvm, fn.asLLVM(), buf.baseAddress!, UInt32(buf.count), next.llvm, `catch`.llvm, name)
1002+
return Invoke(llvm: LLVMBuildInvoke(llvm, fn.asLLVM(), buf.baseAddress!, UInt32(buf.count), next.llvm, `catch`.llvm, name))
10031003
}
10041004
}
10051005

0 commit comments

Comments
 (0)