@@ -935,15 +935,107 @@ public class IRBuilder {
935935 /// - parameter args: A list of arguments.
936936 /// - parameter name: The name for the newly inserted instruction.
937937 ///
938- /// - returns: A value representing `void`.
939- @discardableResult
938+ /// - returns: A value representing the result of returning from the callee.
940939 public func buildCall( _ fn: IRValue , args: [ IRValue ] , name: String = " " ) -> IRValue {
941940 var args = args. map { $0. asLLVM ( ) as Optional }
942941 return args. withUnsafeMutableBufferPointer { buf in
943942 return LLVMBuildCall ( llvm, fn. asLLVM ( ) , buf. baseAddress!, UInt32 ( buf. count) , name)
944943 }
945944 }
946945
946+ // MARK: Exception Handling Instructions
947+
948+ /// Build a call to the given function with the given arguments with the
949+ /// possibility of control transfering to either the `next` basic block or
950+ /// the `catch` basic block if an exception occurs.
951+ ///
952+ /// If the callee function returns with the `ret` instruction, control flow
953+ /// will return to the `next` label. If the callee (or any indirect callees)
954+ /// returns via the `resume` instruction or other exception handling
955+ /// mechanism, control is interrupted and continued at the dynamically nearest
956+ /// `exception` label.
957+ ///
958+ ///
959+ /// - parameter fn: The function to invoke.
960+ /// - parameter args: A list of arguments.
961+ /// - parameter next: The destination block if the invoke succeeds without exceptions.
962+ /// - parameter catch: The destination block if the invoke encounters an exception.
963+ /// - parameter name: The name for the newly inserted instruction.
964+ ///
965+ /// - returns: A value representing the result of returning from the callee
966+ /// under normal circumstances. Under exceptional circumstances, the value
967+ /// represents the value of any `resume` instruction in the `catch` block.
968+ public func buildInvoke( _ fn: IRValue , args: [ IRValue ] , next: BasicBlock , catch: BasicBlock , name: String = " " ) -> IRValue {
969+ precondition ( `catch`. firstInstruction!. opCode == . landingPad, " First instruction of catch block must be a landing pad " )
970+
971+ var args = args. map { $0. asLLVM ( ) as Optional }
972+ return args. withUnsafeMutableBufferPointer { buf in
973+ return LLVMBuildInvoke ( llvm, fn. asLLVM ( ) , buf. baseAddress!, UInt32 ( buf. count) , next. llvm, `catch`. llvm, name)
974+ }
975+ }
976+
977+ /// Build a landing pad to specify that a basic block is where an exception
978+ /// lands, and corresponds to the code found in the `catch` portion of a
979+ /// `try/catch` sequence.
980+ ///
981+ /// The clauses are applied in order from top to bottom. If two landing pad
982+ /// instructions are merged together through inlining, the clauses from the
983+ /// calling function are appended to the list of clauses. When the call stack
984+ /// is being unwound due to an exception being thrown, the exception is
985+ /// compared against each clause in turn. If it doesn’t match any of the
986+ /// clauses, and the cleanup flag is not set, then unwinding continues further
987+ /// up the call stack.
988+ ///
989+ /// The landingpad instruction has several restrictions:
990+ ///
991+ /// - A landing pad block is a basic block which is the unwind destination of
992+ /// an `invoke` instruction.
993+ /// - A landing pad block must have a `landingpad` instruction as its first
994+ /// non-PHI instruction.
995+ /// - There can be only one `landingpad` instruction within the landing pad
996+ /// block.
997+ /// - A basic block that is not a landing pad block may not include a
998+ /// `landingpad` instruction.
999+ ///
1000+ /// - parameter type: The type of the resulting value from the landing pad.
1001+ /// - parameter personalityFn: The personality function.
1002+ /// - parameter clauses: A list of `catch` and `filter` clauses. This list
1003+ /// must either be non-empty or the landing pad must be marked as a cleanup
1004+ /// instruction.
1005+ /// - parameter cleanup: A flag indicating whether the landing pad is a
1006+ /// cleanup.
1007+ /// - parameter name: The name for the newly inserted instruction.
1008+ ///
1009+ /// - returns: A value of the given type representing the result of matching
1010+ /// a clause during unwinding.
1011+ public func buildLandingPad( returning type: IRType , personalityFn: Function ? = nil , clauses: [ LandingPadClause ] , cleanup: Bool = false , name: String = " " ) -> IRValue {
1012+ precondition ( cleanup || !clauses. isEmpty, " Landing pad must be created with clauses or as cleanup " )
1013+
1014+ let lp : IRValue = LLVMBuildLandingPad ( llvm, type. asLLVM ( ) , personalityFn? . asLLVM ( ) , UInt32 ( clauses. count) , name)
1015+ for clause in clauses {
1016+ LLVMAddClause ( lp. asLLVM ( ) , clause. asLLVM ( ) )
1017+ }
1018+ LLVMSetCleanup ( lp. asLLVM ( ) , cleanup. llvm)
1019+ return lp
1020+ }
1021+
1022+ /// Build a resume instruction to resume propagation of an existing
1023+ /// (in-flight) exception whose unwinding was interrupted with a
1024+ /// `landingpad` instruction.
1025+ ///
1026+ /// When all cleanups are finished, if an exception is not handled by the
1027+ /// current function, unwinding resumes by calling the resume instruction,
1028+ /// passing in the result of the `landingpad` instruction for the original
1029+ /// landing pad.
1030+ ///
1031+ /// - parameter: A value representing the result of the original landing pad.
1032+ ///
1033+ /// - returns: A value representing `void`.
1034+ @discardableResult
1035+ public func buildResume( _ val: IRValue ) -> IRValue {
1036+ return LLVMBuildResume ( llvm, val. asLLVM ( ) )
1037+ }
1038+
9471039 // MARK: Memory Access Instructions
9481040
9491041 /// Build an `alloca` to allocate stack memory to hold a value of the given
0 commit comments