1626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner//===-- ExceptionDemo.cpp - An example using llvm Exceptions --------------===//
2a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
3a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//                     The LLVM Compiler Infrastructure
4a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
5a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// This file is distributed under the University of Illinois Open Source
6a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// License. See LICENSE.TXT for details.
7a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
8626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner//===----------------------------------------------------------------------===//
9a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
10a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Demo program which implements an example LLVM exception implementation, and
11a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// shows several test cases including the handling of foreign exceptions.
12a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// It is run with type info types arguments to throw. A test will
139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// be run for each given type info type. While type info types with the value
14a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// of -1 will trigger a foreign C++ exception to be thrown; type info types
159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// <= 6 and >= 1 will cause the associated generated exceptions to be thrown
16a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// and caught by generated test functions; and type info types > 6
17a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// will result in exceptions which pass through to the test harness. All other
18a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// type info types are not supported and could cause a crash. In all cases,
199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// the "finally" blocks of every generated test functions will executed
20a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// regardless of whether or not that test function ignores or catches the
21a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// thrown exception.
22a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
23a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// examples:
24a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
25a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// ExceptionDemo
26a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
27a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//     causes a usage to be printed to stderr
289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi//
29a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// ExceptionDemo 2 3 7 -1
30a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
31a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//     results in the following cases:
329f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi//         - Value 2 causes an exception with a type info type of 2 to be
33a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//           thrown and caught by an inner generated test function.
349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi//         - Value 3 causes an exception with a type info type of 3 to be
35a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//           thrown and caught by an outer generated test function.
369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi//         - Value 7 causes an exception with a type info type of 7 to be
37a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//           thrown and NOT be caught by any generated function.
38a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//         - Value -1 causes a foreign C++ exception to be thrown and not be
39a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//           caught by any generated function
40a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
41a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//     Cases -1 and 7 are caught by a C++ test harness where the validity of
429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi//         of a C++ catch(...) clause catching a generated exception with a
439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi//         type info type of 7 is explained by: example in rules 1.6.4 in
44a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko//         http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22)
45a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// This code uses code from the llvm compiler-rt project and the llvm
47a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Kaleidoscope project.
48a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
49626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner//===----------------------------------------------------------------------===//
50a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
514ca7e09b7c1e41535f2a1bd86915375d023daf27Chandler Carruth#include "llvm/Analysis/Verifier.h"
52c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola#include "llvm/ExecutionEngine/MCJIT.h"
53c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola#include "llvm/ExecutionEngine/SectionMemoryManager.h"
540a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/DataLayout.h"
550a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/DerivedTypes.h"
560a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/IRBuilder.h"
570a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/Intrinsics.h"
580a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/LLVMContext.h"
590a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/Module.h"
60a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#include "llvm/PassManager.h"
61a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#include "llvm/Support/Dwarf.h"
623e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetSelect.h"
634ca7e09b7c1e41535f2a1bd86915375d023daf27Chandler Carruth#include "llvm/Target/TargetOptions.h"
644ca7e09b7c1e41535f2a1bd86915375d023daf27Chandler Carruth#include "llvm/Transforms/Scalar.h"
65a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// FIXME: Although all systems tested with (Linux, OS X), do not need this
679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi//        header file included. A user on ubuntu reported, undefined symbols
6818bba84d7782e978caebddbd98b39e555c63b4dcGarrison Venn//        for stderr, and fprintf, and the addition of this include fixed the
699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi//        issue for them. Given that LLVM's best practices include the goal
709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi//        of reducing the number of redundant header files included, the
719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi//        correct solution would be to find out why these symbols are not
7218bba84d7782e978caebddbd98b39e555c63b4dcGarrison Venn//        defined for the system in question, and fix the issue by finding out
7318bba84d7782e978caebddbd98b39e555c63b4dcGarrison Venn//        which LLVM header file, if any, would include these symbols.
742a7d4ad1f4f008ba4820782331464aedccd969d5Garrison Venn#include <cstdio>
7518bba84d7782e978caebddbd98b39e555c63b4dcGarrison Venn
76a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#include <sstream>
77a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#include <stdexcept>
78a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
79a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
80a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifndef USE_GLOBAL_STR_CONSTS
81a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#define USE_GLOBAL_STR_CONSTS true
82a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
83a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
849f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// System C++ ABI unwind types from:
85a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko//     http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22)
86a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
87a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennextern "C" {
889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
89626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  typedef enum {
90a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _URC_NO_REASON = 0,
91a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
92a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _URC_FATAL_PHASE2_ERROR = 2,
93a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _URC_FATAL_PHASE1_ERROR = 3,
94a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _URC_NORMAL_STOP = 4,
95a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _URC_END_OF_STACK = 5,
96a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _URC_HANDLER_FOUND = 6,
97a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _URC_INSTALL_CONTEXT = 7,
98a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _URC_CONTINUE_UNWIND = 8
99626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  } _Unwind_Reason_Code;
1009f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
101626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  typedef enum {
102a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _UA_SEARCH_PHASE = 1,
103a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _UA_CLEANUP_PHASE = 2,
104a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _UA_HANDLER_FRAME = 4,
105a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _UA_FORCE_UNWIND = 8,
106a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _UA_END_OF_STACK = 16
107626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  } _Unwind_Action;
1089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
109626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  struct _Unwind_Exception;
1109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
111626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
112626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                struct _Unwind_Exception *);
1139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
114626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  struct _Unwind_Exception {
115a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    uint64_t exception_class;
116a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    _Unwind_Exception_Cleanup_Fn exception_cleanup;
1179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1189f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    uintptr_t private_1;
1199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    uintptr_t private_2;
1209f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
121a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    // @@@ The IA-64 ABI says that this structure must be double-word aligned.
1229f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    //  Taking that literally does not make much sense generically.  Instead
123a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    //  we provide the maximum alignment required by any type for the machine.
124626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  } __attribute__((__aligned__));
1259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
126626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  struct _Unwind_Context;
12764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  typedef struct _Unwind_Context *_Unwind_Context_t;
1289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
12964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  extern const uint8_t *_Unwind_GetLanguageSpecificData (_Unwind_Context_t c);
130626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  extern uintptr_t _Unwind_GetGR (_Unwind_Context_t c, int i);
131626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  extern void _Unwind_SetGR (_Unwind_Context_t c, int i, uintptr_t n);
132626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  extern void _Unwind_SetIP (_Unwind_Context_t, uintptr_t new_value);
133626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  extern uintptr_t _Unwind_GetIP (_Unwind_Context_t context);
134626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  extern uintptr_t _Unwind_GetRegionStart (_Unwind_Context_t context);
1359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
136a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} // extern "C"
137a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
138a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
139a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Example types
140a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
141a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
142a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// This is our simplistic type info
143a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstruct OurExceptionType_t {
144626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  /// type info type
145626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  int type;
146a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn};
147a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
148a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
149a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// This is our Exception class which relies on a negative offset to calculate
150a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// pointers to its instances from pointers to its unwindException member.
1519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi///
152a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Note: The above unwind.h defines struct _Unwind_Exception to be aligned
153a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///       on a double word boundary. This is necessary to match the standard:
154a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko///       http://mentorembedded.github.com/cxx-abi/abi-eh.html
155a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstruct OurBaseException_t {
156626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  struct OurExceptionType_t type;
1579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
158626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Note: This is properly aligned in unwind.h
159626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  struct _Unwind_Exception unwindException;
160a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn};
161a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
162a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
163a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Note: Not needed since we are C++
164a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venntypedef struct OurBaseException_t OurException;
165a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venntypedef struct _Unwind_Exception OurUnwindException;
166a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
167a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
1689f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// Various globals used to support typeinfo and generatted exceptions in
169a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// general
170a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
171a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
172a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic std::map<std::string, llvm::Value*> namedValues;
173a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
174a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennint64_t ourBaseFromUnwindOffset;
175a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumiconst unsigned char ourBaseExcpClassChars[] =
177626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner{'o', 'b', 'j', '\0', 'b', 'a', 's', '\0'};
178a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
179a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
180a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic uint64_t ourBaseExceptionClass = 0;
181a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
182a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic std::vector<std::string> ourTypeInfoNames;
183a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic std::map<int, std::string> ourTypeInfoNamesIndex;
184a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
18564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::StructType *ourTypeInfoType;
18685500714c460be6452a96be1574d8676d062051cGarrison Vennstatic llvm::StructType *ourCaughtResultType;
18764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::StructType *ourExceptionType;
18864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::StructType *ourUnwindExceptionType;
189a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
19064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::ConstantInt *ourExceptionNotThrownState;
19164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::ConstantInt *ourExceptionThrownState;
19264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::ConstantInt *ourExceptionCaughtState;
193a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
194a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venntypedef std::vector<std::string> ArgNames;
1956e6cdd00aaca083779eb70dc238779935da6b9c8Garrison Venntypedef std::vector<llvm::Type*> ArgTypes;
196a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
197a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
198a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Code Generation Utilities
199a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
200a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
201a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Utility used to create a function, both declarations and definitions
202a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module for module instance
203a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param retType function return type
204a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param theArgTypes function's ordered argument types
205a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param theArgNames function's ordered arguments needed if use of this
2069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi///        function corresponds to a function definition. Use empty
207a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        aggregate for function declarations.
208a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param functName function name
209a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param linkage function linkage
210a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param declarationOnly for function declarations
211a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param isVarArg function uses vararg arguments
212a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns function instance
21364cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennllvm::Function *createFunction(llvm::Module &module,
21477613d4135d5fc8461d0583837b5b850c4a29ecdChris Lattner                               llvm::Type *retType,
21564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                               const ArgTypes &theArgTypes,
21664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                               const ArgNames &theArgNames,
21764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                               const std::string &functName,
218a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn                               llvm::GlobalValue::LinkageTypes linkage,
219a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn                               bool declarationOnly,
220a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn                               bool isVarArg) {
221626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::FunctionType *functType =
222626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    llvm::FunctionType::get(retType, theArgTypes, isVarArg);
223626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::Function *ret =
224626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    llvm::Function::Create(functType, linkage, functName, &module);
225626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (!ret || declarationOnly)
226a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    return(ret);
2279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
228626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  namedValues.clear();
2299f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  unsigned i = 0;
230626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  for (llvm::Function::arg_iterator argIndex = ret->arg_begin();
231626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner       i != theArgNames.size();
232626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner       ++argIndex, ++i) {
2339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
234626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    argIndex->setName(theArgNames[i]);
235626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    namedValues[theArgNames[i]] = argIndex;
236626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
2379f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
238626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(ret);
239a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
240a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
241a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
242a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Create an alloca instruction in the entry block of
243a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// the parent function.  This is used for mutable variables etc.
244a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param function parent instance
245a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param varName stack variable name
246a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param type stack variable type
247a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param initWith optional constant initialization value
248a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns AllocaInst instance
24964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function,
250626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                const std::string &varName,
25177613d4135d5fc8461d0583837b5b850c4a29ecdChris Lattner                                                llvm::Type *type,
25264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                                llvm::Constant *initWith = 0) {
2539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::BasicBlock &block = function.getEntryBlock();
254626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::IRBuilder<> tmp(&block, block.begin());
25564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::AllocaInst *ret = tmp.CreateAlloca(type, 0, varName.c_str());
2569f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
2579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  if (initWith)
258626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    tmp.CreateStore(initWith, ret);
2599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
260626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(ret);
261a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
262a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
263a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
264a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
265a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Code Generation Utilities End
266a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
267a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
268a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
2699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi// Runtime C Library functions
270a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
271a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
272a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Note: using an extern "C" block so that static functions can be used
273a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennextern "C" {
274a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
275a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Note: Better ways to decide on bit width
276a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
277a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Prints a 32 bit number, according to the format, to stderr.
2789f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param intToPrint integer to print
279a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param format printf like format to use when printing
28064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennvoid print32Int(int intToPrint, const char *format) {
281626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (format) {
282626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Note: No NULL check
283626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, format, intToPrint);
284626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
285626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  else {
286626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Note: No NULL check
287626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, "::print32Int(...):NULL arg.\n");
288626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
289a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
290a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
291a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
292a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Note: Better ways to decide on bit width
293a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
294a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Prints a 64 bit number, according to the format, to stderr.
2959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param intToPrint integer to print
296a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param format printf like format to use when printing
29764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennvoid print64Int(long int intToPrint, const char *format) {
298626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (format) {
299626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Note: No NULL check
300626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, format, intToPrint);
301626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
302626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  else {
303626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Note: No NULL check
304626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, "::print64Int(...):NULL arg.\n");
305626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
306a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
307a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
308a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
309a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Prints a C string to stderr
310a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toPrint string to print
31164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennvoid printStr(char *toPrint) {
312626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (toPrint) {
313626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, "%s", toPrint);
314626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
315626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  else {
316626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, "::printStr(...):NULL arg.\n");
317626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
318a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
319a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
320a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
321a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Deletes the true previosly allocated exception whose address
322a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// is calculated from the supplied OurBaseException_t::unwindException
323a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// member address. Handles (ignores), NULL pointers.
324a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param expToDelete exception to delete
32564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennvoid deleteOurException(OurUnwindException *expToDelete) {
326a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
327626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  fprintf(stderr,
328626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          "deleteOurException(...).\n");
329a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
3309f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
331626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (expToDelete &&
332626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      (expToDelete->exception_class == ourBaseExceptionClass)) {
3339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
334626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    free(((char*) expToDelete) + ourBaseFromUnwindOffset);
335626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
336a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
337a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
338a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
3399f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// This function is the struct _Unwind_Exception API mandated delete function
3409f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// used by foreign exception handlers when deleting our exception
341a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// (OurException), instances.
342c16babf6939f9db05a8a81c4d530a2fd605b4236NAKAMURA Takumi/// @param reason See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html
343a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @unlink
344a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param expToDelete exception instance to delete
345a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennvoid deleteFromUnwindOurException(_Unwind_Reason_Code reason,
34664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                  OurUnwindException *expToDelete) {
347a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
348626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  fprintf(stderr,
349626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          "deleteFromUnwindOurException(...).\n");
350a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
3519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
352626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  deleteOurException(expToDelete);
353a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
354a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
355a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
356a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Creates (allocates on the heap), an exception (OurException instance),
357a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// of the supplied type info type.
358a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param type type info type
35964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison VennOurUnwindException *createOurException(int type) {
360626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  size_t size = sizeof(OurException);
36164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  OurException *ret = (OurException*) memset(malloc(size), 0, size);
362626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  (ret->type).type = type;
363626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  (ret->unwindException).exception_class = ourBaseExceptionClass;
364626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  (ret->unwindException).exception_cleanup = deleteFromUnwindOurException;
3659f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
366626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(&(ret->unwindException));
367a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
368a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
369a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
3709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Read a uleb128 encoded value and advance pointer
3719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// See Variable Length Data in:
372a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
373a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param data reference variable holding memory pointer to decode from
374a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns decoded value
37564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic uintptr_t readULEB128(const uint8_t **data) {
376626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uintptr_t result = 0;
377626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uintptr_t shift = 0;
378626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  unsigned char byte;
37964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  const uint8_t *p = *data;
3809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
381626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  do {
382626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    byte = *p++;
383626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    result |= (byte & 0x7f) << shift;
384626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    shift += 7;
3859f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  }
386626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  while (byte & 0x80);
3879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
388626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  *data = p;
3899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
390626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return result;
391a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
392a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
393a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
3949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Read a sleb128 encoded value and advance pointer
3959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// See Variable Length Data in:
396a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
397a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param data reference variable holding memory pointer to decode from
398a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns decoded value
39964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic uintptr_t readSLEB128(const uint8_t **data) {
400626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uintptr_t result = 0;
401626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uintptr_t shift = 0;
402626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  unsigned char byte;
40364cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  const uint8_t *p = *data;
4049f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
405626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  do {
406626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    byte = *p++;
407626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    result |= (byte & 0x7f) << shift;
408626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    shift += 7;
4099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  }
410626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  while (byte & 0x80);
4119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
412626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  *data = p;
4139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
414626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if ((byte & 0x40) && (shift < (sizeof(result) << 3))) {
415626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    result |= (~0 << shift);
416626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
4179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
418626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return result;
419a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
420a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
42158c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindolaunsigned getEncodingSize(uint8_t Encoding) {
42258c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  if (Encoding == llvm::dwarf::DW_EH_PE_omit)
42358c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    return 0;
42458c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola
42558c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  switch (Encoding & 0x0F) {
42658c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  case llvm::dwarf::DW_EH_PE_absptr:
42758c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    return sizeof(uintptr_t);
42858c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  case llvm::dwarf::DW_EH_PE_udata2:
42958c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    return sizeof(uint16_t);
43058c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  case llvm::dwarf::DW_EH_PE_udata4:
43158c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    return sizeof(uint32_t);
43258c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  case llvm::dwarf::DW_EH_PE_udata8:
43358c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    return sizeof(uint64_t);
43458c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  case llvm::dwarf::DW_EH_PE_sdata2:
43558c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    return sizeof(int16_t);
43658c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  case llvm::dwarf::DW_EH_PE_sdata4:
43758c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    return sizeof(int32_t);
43858c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  case llvm::dwarf::DW_EH_PE_sdata8:
43958c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    return sizeof(int64_t);
44058c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  default:
44158c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    // not supported
44258c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    abort();
44358c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  }
44458c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola}
445a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
4469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Read a pointer encoded value and advance pointer
4479f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// See Variable Length Data in:
448a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
449a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param data reference variable holding memory pointer to decode from
450a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param encoding dwarf encoding type
451a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns decoded value
45264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennstatic uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
453626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uintptr_t result = 0;
45464cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  const uint8_t *p = *data;
4559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
4569f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  if (encoding == llvm::dwarf::DW_EH_PE_omit)
457626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    return(result);
4589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
4599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // first get value
460626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  switch (encoding & 0x0F) {
461626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_absptr:
462626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      result = *((uintptr_t*)p);
463626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      p += sizeof(uintptr_t);
464626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
465626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_uleb128:
466626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      result = readULEB128(&p);
467626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
468626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      // Note: This case has not been tested
469626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_sleb128:
470626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      result = readSLEB128(&p);
471626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
472626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_udata2:
473626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      result = *((uint16_t*)p);
474626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      p += sizeof(uint16_t);
475626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
476626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_udata4:
477626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      result = *((uint32_t*)p);
478626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      p += sizeof(uint32_t);
479626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
480626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_udata8:
481626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      result = *((uint64_t*)p);
482626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      p += sizeof(uint64_t);
483626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
484626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_sdata2:
485626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      result = *((int16_t*)p);
486626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      p += sizeof(int16_t);
487626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
488626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_sdata4:
489626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      result = *((int32_t*)p);
490626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      p += sizeof(int32_t);
491626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
492626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_sdata8:
493626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      result = *((int64_t*)p);
494626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      p += sizeof(int64_t);
495626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
496626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    default:
4979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi      // not supported
498626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      abort();
499626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
500626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
5019f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
5029f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // then add relative offset
503626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  switch (encoding & 0x70) {
504626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_absptr:
5059f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi      // do nothing
506626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
507626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_pcrel:
508626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      result += (uintptr_t)(*data);
509626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
510626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_textrel:
511626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_datarel:
512626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_funcrel:
513626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    case llvm::dwarf::DW_EH_PE_aligned:
514626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    default:
5159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi      // not supported
516626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      abort();
517626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
518626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
5199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
5209f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // then apply indirection
521626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (encoding & llvm::dwarf::DW_EH_PE_indirect) {
522626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    result = *((uintptr_t*)result);
523626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
5249f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
525626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  *data = p;
5269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
527626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return result;
528a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
529a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
530a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
5319f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Deals with Dwarf actions matching our type infos
5329f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// (OurExceptionType_t instances). Returns whether or not a dwarf emitted
5339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// action matches the supplied exception type. If such a match succeeds,
5349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// the resultAction argument will be set with > 0 index value. Only
5359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// corresponding llvm.eh.selector type info arguments, cleanup arguments
536a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// are supported. Filters are not supported.
5379f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// See Variable Length Data in:
538a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
539a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko/// Also see @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
540a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param resultAction reference variable which will be set with result
541a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param classInfo our array of type info pointers (to globals)
5429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param actionEntry index into above type info array or 0 (clean up).
543a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        We do not support filters.
544a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionClass exception class (_Unwind_Exception::exception_class)
545a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        of thrown exception.
546a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionObject thrown _Unwind_Exception instance.
547a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns whether or not a type info was found. False is returned if only
548a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///          a cleanup was found
549a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic bool handleActionValue(int64_t *resultAction,
55058c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola                              uint8_t TTypeEncoding,
55158c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola                              const uint8_t *ClassInfo,
5529f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                              uintptr_t actionEntry,
5539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                              uint64_t exceptionClass,
554a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn                              struct _Unwind_Exception *exceptionObject) {
555626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  bool ret = false;
5569f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
5579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  if (!resultAction ||
5589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi      !exceptionObject ||
559626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      (exceptionClass != ourBaseExceptionClass))
560626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    return(ret);
5619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
56264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  struct OurBaseException_t *excp = (struct OurBaseException_t*)
563626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  (((char*) exceptionObject) + ourBaseFromUnwindOffset);
564626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  struct OurExceptionType_t *excpType = &(excp->type);
565626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  int type = excpType->type;
5669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
567a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
568626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  fprintf(stderr,
569626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          "handleActionValue(...): exceptionObject = <%p>, "
570626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          "excp = <%p>.\n",
571626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          exceptionObject,
572626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          excp);
573a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
5749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
575626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  const uint8_t *actionPos = (uint8_t*) actionEntry,
576626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  *tempActionPos;
577626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  int64_t typeOffset = 0,
578626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  actionOffset;
5799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
580626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  for (int i = 0; true; ++i) {
581626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Each emitted dwarf action corresponds to a 2 tuple of
582626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // type info address offset, and action offset to the next
583626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // emitted action.
584626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    typeOffset = readSLEB128(&actionPos);
585626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    tempActionPos = actionPos;
586626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    actionOffset = readSLEB128(&tempActionPos);
5879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
588a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
589626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr,
590626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "handleActionValue(...):typeOffset: <%lld>, "
591626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "actionOffset: <%lld>.\n",
592626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            typeOffset,
593626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            actionOffset);
594a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
5959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    assert((typeOffset >= 0) &&
596626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner           "handleActionValue(...):filters are not supported.");
5979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
598626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector
599626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    //       argument has been matched.
60058c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    if (typeOffset > 0) {
601a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
602626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      fprintf(stderr,
603626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner              "handleActionValue(...):actionValue <%d> found.\n",
604626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner              i);
605a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
60658c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola      unsigned EncSize = getEncodingSize(TTypeEncoding);
60758c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola      const uint8_t *EntryP = ClassInfo - typeOffset * EncSize;
60858c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola      uintptr_t P = readEncodedPointer(&EntryP, TTypeEncoding);
60958c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola      struct OurExceptionType_t *ThisClassInfo =
61058c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola        reinterpret_cast<struct OurExceptionType_t *>(P);
61158c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola      if (ThisClassInfo->type == type) {
61258c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola        *resultAction = i + 1;
61358c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola        ret = true;
61458c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola        break;
61558c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola      }
616626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    }
6179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
618a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
619626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr,
620626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "handleActionValue(...):actionValue not found.\n");
621a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
622626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    if (!actionOffset)
623626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
6249f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
625626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    actionPos += actionOffset;
626626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
6279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
628626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(ret);
629a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
630a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
631a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
632a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Deals with the Language specific data portion of the emitted dwarf code.
633a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
634a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param version unsupported (ignored), unwind version
635a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param lsda language specific data area
6369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param _Unwind_Action actions minimally supported unwind stage
637a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        (forced specifically not supported)
638a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionClass exception class (_Unwind_Exception::exception_class)
639a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        of thrown exception.
640a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionObject thrown _Unwind_Exception instance.
641a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context unwind system context
6429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @returns minimally supported unwinding control indicator
6439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumistatic _Unwind_Reason_Code handleLsda(int version,
64464cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                      const uint8_t *lsda,
645626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                      _Unwind_Action actions,
6469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                      uint64_t exceptionClass,
64764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                    struct _Unwind_Exception *exceptionObject,
648626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                      _Unwind_Context_t context) {
649626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  _Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND;
6509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
651626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (!lsda)
652626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    return(ret);
6539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
654a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
6559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  fprintf(stderr,
656626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          "handleLsda(...):lsda is non-zero.\n");
657a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
6589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
659626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Get the current instruction pointer and offset it before next
660626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // instruction in the current frame which threw the exception.
661626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uintptr_t pc = _Unwind_GetIP(context)-1;
6629f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
6639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // Get beginning current frame's code (as defined by the
664626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // emitted dwarf code)
665626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uintptr_t funcStart = _Unwind_GetRegionStart(context);
666626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uintptr_t pcOffset = pc - funcStart;
66758c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola  const uint8_t *ClassInfo = NULL;
6689f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
669626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
670626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  //       dwarf emission
6719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
672626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Parse LSDA header.
673626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uint8_t lpStartEncoding = *lsda++;
6749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
675626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (lpStartEncoding != llvm::dwarf::DW_EH_PE_omit) {
6769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    readEncodedPointer(&lsda, lpStartEncoding);
677626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
6789f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
679626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uint8_t ttypeEncoding = *lsda++;
680626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uintptr_t classInfoOffset;
6819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
682626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (ttypeEncoding != llvm::dwarf::DW_EH_PE_omit) {
683626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Calculate type info locations in emitted dwarf code which
684626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // were flagged by type info arguments to llvm.eh.selector
685626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // intrinsic
686626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    classInfoOffset = readULEB128(&lsda);
68758c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola    ClassInfo = lsda + classInfoOffset;
688626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
6899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
6909f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // Walk call-site table looking for range that
6919f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // includes current PC.
6929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
693626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uint8_t         callSiteEncoding = *lsda++;
694626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uint32_t        callSiteTableLength = readULEB128(&lsda);
69564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  const uint8_t   *callSiteTableStart = lsda;
6969f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  const uint8_t   *callSiteTableEnd = callSiteTableStart +
697626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  callSiteTableLength;
69864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  const uint8_t   *actionTableStart = callSiteTableEnd;
69964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  const uint8_t   *callSitePtr = callSiteTableStart;
7009f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
701626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  while (callSitePtr < callSiteTableEnd) {
7029f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    uintptr_t start = readEncodedPointer(&callSitePtr,
703626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                         callSiteEncoding);
7049f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    uintptr_t length = readEncodedPointer(&callSitePtr,
705626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                          callSiteEncoding);
7069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    uintptr_t landingPad = readEncodedPointer(&callSitePtr,
707a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn                                              callSiteEncoding);
7089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
709626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Note: Action value
710626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    uintptr_t actionEntry = readULEB128(&callSitePtr);
7119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
712626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    if (exceptionClass != ourBaseExceptionClass) {
713626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      // We have been notified of a foreign exception being thrown,
714626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      // and we therefore need to execute cleanup landing pads
715626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      actionEntry = 0;
716626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    }
7179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
718626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    if (landingPad == 0) {
719a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
720626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      fprintf(stderr,
721626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner              "handleLsda(...): No landing pad found.\n");
722a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
7239f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
724626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      continue; // no landing pad for this entry
725626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    }
7269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
727626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    if (actionEntry) {
728626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      actionEntry += ((uintptr_t) actionTableStart) - 1;
729626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    }
730626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    else {
731a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
732626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      fprintf(stderr,
733626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner              "handleLsda(...):No action table found.\n");
734a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
735626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    }
7369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
737626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    bool exceptionMatched = false;
7389f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
739626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    if ((start <= pcOffset) && (pcOffset < (start + length))) {
740a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
741626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      fprintf(stderr,
742626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner              "handleLsda(...): Landing pad found.\n");
743a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
744626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      int64_t actionValue = 0;
7459f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
746626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      if (actionEntry) {
74764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn        exceptionMatched = handleActionValue(&actionValue,
74858c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola                                             ttypeEncoding,
74958c3aa204906def9a157ea9a9db091f69af76e4bRafael Espindola                                             ClassInfo,
7509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                             actionEntry,
7519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                             exceptionClass,
75264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                             exceptionObject);
753626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      }
7549f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
755626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      if (!(actions & _UA_SEARCH_PHASE)) {
756a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
757626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        fprintf(stderr,
758626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                "handleLsda(...): installed landing pad "
759626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                "context.\n");
760a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
7619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
762626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        // Found landing pad for the PC.
7639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi        // Set Instruction Pointer to so we re-enter function
7649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi        // at landing pad. The landing pad is created by the
765626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        // compiler to take two parameters in registers.
7669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi        _Unwind_SetGR(context,
7679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                      __builtin_eh_return_data_regno(0),
768626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      (uintptr_t)exceptionObject);
7699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
770626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        // Note: this virtual register directly corresponds
771626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        //       to the return of the llvm.eh.selector intrinsic
772626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        if (!actionEntry || !exceptionMatched) {
773626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          // We indicate cleanup only
7749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi          _Unwind_SetGR(context,
7759f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                        __builtin_eh_return_data_regno(1),
776626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                        0);
777626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        }
778626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        else {
779626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          // Matched type info index of llvm.eh.selector intrinsic
780626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          // passed here.
7819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi          _Unwind_SetGR(context,
7829f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                        __builtin_eh_return_data_regno(1),
783626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                        actionValue);
784626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        }
7859f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
786626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        // To execute landing pad set here
787626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        _Unwind_SetIP(context, funcStart + landingPad);
788626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        ret = _URC_INSTALL_CONTEXT;
789626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      }
790626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      else if (exceptionMatched) {
791a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
792626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        fprintf(stderr,
793626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                "handleLsda(...): setting handler found.\n");
794a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
795626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        ret = _URC_HANDLER_FOUND;
796626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      }
797626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      else {
798626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        // Note: Only non-clean up handlers are marked as
7999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi        //       found. Otherwise the clean up handlers will be
8009f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi        //       re-found and executed during the clean up
801626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        //       phase.
802a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
803626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner        fprintf(stderr,
804626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                "handleLsda(...): cleanup handler found.\n");
805a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
806626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      }
8079f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
808626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      break;
809a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn    }
810626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
8119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
812626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(ret);
813a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
814a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
815a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
816a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// This is the personality function which is embedded (dwarf emitted), in the
817a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// dwarf unwind info block. Again see: JITDwarfEmitter.cpp.
818a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
819a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param version unsupported (ignored), unwind version
8209f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param _Unwind_Action actions minimally supported unwind stage
821a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        (forced specifically not supported)
822a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionClass exception class (_Unwind_Exception::exception_class)
823a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        of thrown exception.
824a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionObject thrown _Unwind_Exception instance.
825a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context unwind system context
8269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @returns minimally supported unwinding control indicator
8279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi_Unwind_Reason_Code ourPersonality(int version,
828626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                   _Unwind_Action actions,
8299f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                   uint64_t exceptionClass,
83064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                   struct _Unwind_Exception *exceptionObject,
831626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                   _Unwind_Context_t context) {
832a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
8339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  fprintf(stderr,
834626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          "We are in ourPersonality(...):actions is <%d>.\n",
835626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          actions);
8369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
837626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (actions & _UA_SEARCH_PHASE) {
838626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, "ourPersonality(...):In search phase.\n");
839626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
840626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  else {
841626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, "ourPersonality(...):In non-search phase.\n");
842626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
843a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
8449f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
84564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  const uint8_t *lsda = _Unwind_GetLanguageSpecificData(context);
8469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
847a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
8489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  fprintf(stderr,
849626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          "ourPersonality(...):lsda = <%p>.\n",
850626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          lsda);
851a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
8529f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
853626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // The real work of the personality function is captured here
854626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(handleLsda(version,
855626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                    lsda,
856626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                    actions,
857626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                    exceptionClass,
858626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                    exceptionObject,
859626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                    context));
860a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
861a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
862a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
863a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Generates our _Unwind_Exception class from a given character array.
864a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// thereby handling arbitrary lengths (not in standard), and handling
865a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// embedded \0s.
866a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
867a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param classChars char array to encode. NULL values not checkedf
868a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param classCharsSize number of chars in classChars. Value is not checked.
869a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns class value
870a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennuint64_t genClass(const unsigned char classChars[], size_t classCharsSize)
871a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn{
872626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  uint64_t ret = classChars[0];
8739f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
874626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  for (unsigned i = 1; i < classCharsSize; ++i) {
875626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    ret <<= 8;
876626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    ret += classChars[i];
877626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
8789f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
879626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(ret);
880a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
881a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
882a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn} // extern "C"
883a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
884a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
885a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Runtime C Library functions End
886a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
887a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
888a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
889a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Code generation functions
890a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
891a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
892a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Generates code to print given constant string
893a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context llvm context
894a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance
895a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance
896a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toPrint string to print
8979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param useGlobal A value of true (default) indicates a GlobalValue is
8989f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi///        generated, and is used to hold the constant string. A value of
8999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi///        false indicates that the constant string will be stored on the
900a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        stack.
9019f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumivoid generateStringPrint(llvm::LLVMContext &context,
90264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                         llvm::Module &module,
9039f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         llvm::IRBuilder<> &builder,
904a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn                         std::string toPrint,
905a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn                         bool useGlobal = true) {
906626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::Function *printFunct = module.getFunction("printStr");
9079f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
908626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::Value *stringVar;
9099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::Constant *stringConstant =
910793a32dfb643c2804b79d7d675cc614659debae7Peter Collingbourne  llvm::ConstantDataArray::getString(context, toPrint);
9119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
912626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (useGlobal) {
913626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Note: Does not work without allocation
9149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    stringVar =
9159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    new llvm::GlobalVariable(module,
916626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                             stringConstant->getType(),
9179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                             true,
9189f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                             llvm::GlobalValue::LinkerPrivateLinkage,
9199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                             stringConstant,
920626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                             "");
921626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
922626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  else {
923626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    stringVar = builder.CreateAlloca(stringConstant->getType());
924626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    builder.CreateStore(stringConstant, stringVar);
925626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
9269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
9279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::Value *cast = builder.CreatePointerCast(stringVar,
9289cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                builder.getInt8PtrTy());
929626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateCall(printFunct, cast);
930a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
931a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
932a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
933a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Generates code to print given runtime integer according to constant
934a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// string format, and a given print function.
935a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context llvm context
936a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance
937a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance
938a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param printFunct function used to "print" integer
939a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toPrint string to print
940a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param format printf like formating string for print
9419f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param useGlobal A value of true (default) indicates a GlobalValue is
9429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi///        generated, and is used to hold the constant string. A value of
9439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi///        false indicates that the constant string will be stored on the
944a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        stack.
9459f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumivoid generateIntegerPrint(llvm::LLVMContext &context,
94664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                          llvm::Module &module,
9479f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                          llvm::IRBuilder<> &builder,
94864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                          llvm::Function &printFunct,
94964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                          llvm::Value &toPrint,
9509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                          std::string format,
951a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn                          bool useGlobal = true) {
952793a32dfb643c2804b79d7d675cc614659debae7Peter Collingbourne  llvm::Constant *stringConstant =
953793a32dfb643c2804b79d7d675cc614659debae7Peter Collingbourne    llvm::ConstantDataArray::getString(context, format);
954626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::Value *stringVar;
9559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
956626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (useGlobal) {
957626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Note: Does not seem to work without allocation
9589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    stringVar =
9599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    new llvm::GlobalVariable(module,
960626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                             stringConstant->getType(),
9619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                             true,
9629f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                             llvm::GlobalValue::LinkerPrivateLinkage,
9639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                             stringConstant,
964626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                             "");
965626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
966626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  else {
967626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    stringVar = builder.CreateAlloca(stringConstant->getType());
968626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    builder.CreateStore(stringConstant, stringVar);
969626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
9709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
9719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::Value *cast = builder.CreateBitCast(stringVar,
9729cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                            builder.getInt8PtrTy());
973626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateCall2(&printFunct, &toPrint, cast);
974a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
975a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
976a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
9779f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Generates code to handle finally block type semantics: always runs
9789f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// regardless of whether a thrown exception is passing through or the
9799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// parent function is simply exiting. In addition to printing some state
9809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// to stderr, this code will resume the exception handling--runs the
9819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// unwind resume block, if the exception has not been previously caught
9829f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// by a catch clause, and will otherwise execute the end block (terminator
9839f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// block). In addition this function creates the corresponding function's
984a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// stack storage for the exception pointer and catch flag status.
985a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context llvm context
986a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance
987a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance
988a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toAddTo parent function to add block to
989a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param blockName block name of new "finally" block.
990a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param functionId output id used for printing
991a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param terminatorBlock terminator "end" block
992a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param unwindResumeBlock unwind resume block
993a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionCaughtFlag reference exception caught/thrown status storage
994a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionStorage reference to exception pointer storage
9959cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn/// @param caughtResultStorage reference to landingpad result storage
996a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns newly created block
9979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumistatic llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
9989f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                            llvm::Module &module,
9999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                            llvm::IRBuilder<> &builder,
100064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                            llvm::Function &toAddTo,
100164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                            std::string &blockName,
100264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                            std::string &functionId,
100364cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                            llvm::BasicBlock &terminatorBlock,
100464cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                            llvm::BasicBlock &unwindResumeBlock,
100564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                            llvm::Value **exceptionCaughtFlag,
100608e8db423df938160bd611741da4c6dad40ce125Bill Wendling                                            llvm::Value **exceptionStorage,
100708e8db423df938160bd611741da4c6dad40ce125Bill Wendling                                            llvm::Value **caughtResultStorage) {
10089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  assert(exceptionCaughtFlag &&
1009626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner         "ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag "
1010626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner         "is NULL");
10119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  assert(exceptionStorage &&
1012626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner         "ExceptionDemo::createFinallyBlock(...):exceptionStorage "
1013626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner         "is NULL");
10149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  assert(caughtResultStorage &&
10159cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn         "ExceptionDemo::createFinallyBlock(...):caughtResultStorage "
10169cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn         "is NULL");
10179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
10189cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  *exceptionCaughtFlag = createEntryBlockAlloca(toAddTo,
10199cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                         "exceptionCaught",
10209cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                         ourExceptionNotThrownState->getType(),
10219cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                         ourExceptionNotThrownState);
10229f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
102377613d4135d5fc8461d0583837b5b850c4a29ecdChris Lattner  llvm::PointerType *exceptionStorageType = builder.getInt8PtrTy();
10249cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  *exceptionStorage = createEntryBlockAlloca(toAddTo,
10259cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                             "exceptionStorage",
10269cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                             exceptionStorageType,
10279cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                             llvm::ConstantPointerNull::get(
10289cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                               exceptionStorageType));
10299cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  *caughtResultStorage = createEntryBlockAlloca(toAddTo,
10309cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                              "caughtResultStorage",
10319cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                              ourCaughtResultType,
10329cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                              llvm::ConstantAggregateZero::get(
10339cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                ourCaughtResultType));
10349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1035626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
1036626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                   blockName,
1037626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                   &toAddTo);
10389f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1039626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(ret);
10409f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1041626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  std::ostringstream bufferToPrint;
1042626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  bufferToPrint << "Gen: Executing finally block "
1043626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    << blockName << " in " << functionId << "\n";
10449f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  generateStringPrint(context,
10459f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                      module,
10469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                      builder,
1047626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      bufferToPrint.str(),
1048626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      USE_GLOBAL_STR_CONSTS);
10499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
10509cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad(
10519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                       *exceptionCaughtFlag),
10529cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                     &terminatorBlock,
10539cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                     2);
1054626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
1055626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
10569f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1057626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(ret);
1058a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
1059a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1060a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1061a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Generates catch block semantics which print a string to indicate type of
10629f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// catch executed, sets an exception caught flag, and executes passed in
1063a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// end block (terminator block).
1064a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param context llvm context
1065a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance
1066a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance
1067a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toAddTo parent function to add block to
1068a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param blockName block name of new "catch" block.
1069a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param functionId output id used for printing
1070a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param terminatorBlock terminator "end" block
1071a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionCaughtFlag exception caught/thrown status
1072a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns newly created block
10739f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumistatic llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context,
10749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                          llvm::Module &module,
10759f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                          llvm::IRBuilder<> &builder,
107664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                          llvm::Function &toAddTo,
107764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                          std::string &blockName,
107864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                          std::string &functionId,
107964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                          llvm::BasicBlock &terminatorBlock,
108064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                          llvm::Value &exceptionCaughtFlag) {
10819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1082626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
1083626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                   blockName,
1084626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                   &toAddTo);
10859f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1086626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(ret);
10879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1088626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  std::ostringstream bufferToPrint;
1089626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  bufferToPrint << "Gen: Executing catch block "
1090626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  << blockName
1091626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  << " in "
1092626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  << functionId
1093626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  << std::endl;
10949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  generateStringPrint(context,
10959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                      module,
10969f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                      builder,
1097626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      bufferToPrint.str(),
1098626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      USE_GLOBAL_STR_CONSTS);
1099626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateStore(ourExceptionCaughtState, &exceptionCaughtFlag);
1100626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateBr(&terminatorBlock);
11019f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1102626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(ret);
1103a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
1104a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1105a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
11069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Generates a function which invokes a function (toInvoke) and, whose
11079f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// unwind block will "catch" the type info types correspondingly held in the
11089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// exceptionTypesToCatch argument. If the toInvoke function throws an
11099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// exception which does not match any type info types contained in
11109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// exceptionTypesToCatch, the generated code will call _Unwind_Resume
11119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// with the raised exception. On the other hand the generated code will
1112a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// normally exit if the toInvoke function does not throw an exception.
11139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// The generated "finally" block is always run regardless of the cause of
1114a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// the generated function exit.
1115a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// The generated function is returned after being verified.
1116a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance
1117a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance
11189f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param fpm a function pass manager holding optional IR to IR
1119a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        transformations
1120a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param toInvoke inner function to invoke
1121a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param ourId id used to printing purposes
1122a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param numExceptionsToCatch length of exceptionTypesToCatch array
1123a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param exceptionTypesToCatch array of type info types to "catch"
1124a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns generated function
1125a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic
11269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumillvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
11279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                             llvm::IRBuilder<> &builder,
112864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                             llvm::FunctionPassManager &fpm,
112964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                             llvm::Function &toInvoke,
113064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                             std::string ourId,
113164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                             unsigned numExceptionsToCatch,
113264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                             unsigned exceptionTypesToCatch[]) {
11339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
113464cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::LLVMContext &context = module.getContext();
1135626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::Function *toPrint32Int = module.getFunction("print32Int");
11369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1137626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  ArgTypes argTypes;
1138c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt32Ty());
11399f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1140626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  ArgNames argNames;
1141626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argNames.push_back("exceptTypeToThrow");
11429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
11439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::Function *ret = createFunction(module,
1144626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                       builder.getVoidTy(),
11459f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                       argTypes,
11469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                       argNames,
1147626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                       ourId,
11489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                       llvm::Function::ExternalLinkage,
11499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                       false,
1150626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                       false);
11519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1152626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Block which calls invoke
1153626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
11549f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                          "entry",
1155626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                          ret);
1156626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Normal block for invoke
11579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context,
11589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                           "normal",
1159626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                           ret);
1160626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Unwind block for invoke
11619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context,
11629f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                              "exception",
11639cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                              ret);
11649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1165626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Block which routes exception to correct catch handler block
11669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context,
11679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                             "exceptionRoute",
11689cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                             ret);
11699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1170626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Foreign exception handler
11719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context,
11729f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                          "externalException",
11739cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                          ret);
11749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1175626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Block which calls _Unwind_Resume
11769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context,
11779f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                               "unwindResume",
11789cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                               ret);
11799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1180626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Clean up block which delete exception if needed
11819cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::BasicBlock *endBlock = llvm::BasicBlock::Create(context, "end", ret);
11829f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1183626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  std::string nextName;
1184626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  std::vector<llvm::BasicBlock*> catchBlocks(numExceptionsToCatch);
118564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::Value *exceptionCaughtFlag = NULL;
118664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::Value *exceptionStorage = NULL;
11879cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::Value *caughtResultStorage = NULL;
11889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
11899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // Finally block which will branch to unwindResumeBlock if
1190626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // exception is not caught. Initializes/allocates stack locations.
11919f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::BasicBlock *finallyBlock = createFinallyBlock(context,
11929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                      module,
11939f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                      builder,
11949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                      *ret,
11959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                      nextName = "finally",
1196626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                      ourId,
1197626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                      *endBlock,
1198626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                      *unwindResumeBlock,
1199626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                      &exceptionCaughtFlag,
120008e8db423df938160bd611741da4c6dad40ce125Bill Wendling                                                      &exceptionStorage,
120108e8db423df938160bd611741da4c6dad40ce125Bill Wendling                                                      &caughtResultStorage
12029cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                      );
12039f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1204626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
1205626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
12069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1207626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // One catch block per type info to be caught
12089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    catchBlocks[i] = createCatchBlock(context,
12099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                      module,
12109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                      builder,
1211626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                      *ret,
12129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                      nextName,
1213626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                      ourId,
1214626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                      *finallyBlock,
1215626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                      *exceptionCaughtFlag);
1216626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
12179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1218626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Entry Block
12199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1220626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(entryBlock);
12219f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1222626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  std::vector<llvm::Value*> args;
1223626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  args.push_back(namedValues["exceptTypeToThrow"]);
12249f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  builder.CreateInvoke(&toInvoke,
12259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       normalBlock,
12269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       exceptionBlock,
122777613d4135d5fc8461d0583837b5b850c4a29ecdChris Lattner                       args);
12289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1229626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // End Block
12309f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1231626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(endBlock);
12329f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
12339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  generateStringPrint(context,
1234626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      module,
12359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                      builder,
1236626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      "Gen: In end block: exiting in " + ourId + ".\n",
1237626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      USE_GLOBAL_STR_CONSTS);
12389cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::Function *deleteOurException = module.getFunction("deleteOurException");
12399f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1240626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Note: function handles NULL exceptions
12419f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  builder.CreateCall(deleteOurException,
1242626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                     builder.CreateLoad(exceptionStorage));
1243626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateRetVoid();
12449f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1245626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Normal Block
12469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1247626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(normalBlock);
12489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
12499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  generateStringPrint(context,
1250626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      module,
12519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                      builder,
1252626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      "Gen: No exception in " + ourId + "!\n",
1253626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      USE_GLOBAL_STR_CONSTS);
12549f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1255626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Finally block is always called
1256626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateBr(finallyBlock);
12579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1258626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Unwind Resume Block
12599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1260626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(unwindResumeBlock);
12619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
12629cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  builder.CreateResume(builder.CreateLoad(caughtResultStorage));
12639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1264626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Exception Block
12659f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1266626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(exceptionBlock);
12679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
126885500714c460be6452a96be1574d8676d062051cGarrison Venn  llvm::Function *personality = module.getFunction("ourPersonality");
12699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
12709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::LandingPadInst *caughtResult =
127185500714c460be6452a96be1574d8676d062051cGarrison Venn    builder.CreateLandingPad(ourCaughtResultType,
127285500714c460be6452a96be1574d8676d062051cGarrison Venn                             personality,
127385500714c460be6452a96be1574d8676d062051cGarrison Venn                             numExceptionsToCatch,
127485500714c460be6452a96be1574d8676d062051cGarrison Venn                             "landingPad");
127585500714c460be6452a96be1574d8676d062051cGarrison Venn
127685500714c460be6452a96be1574d8676d062051cGarrison Venn  caughtResult->setCleanup(true);
127785500714c460be6452a96be1574d8676d062051cGarrison Venn
127885500714c460be6452a96be1574d8676d062051cGarrison Venn  for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
127985500714c460be6452a96be1574d8676d062051cGarrison Venn    // Set up type infos to be caught
128085500714c460be6452a96be1574d8676d062051cGarrison Venn    caughtResult->addClause(module.getGlobalVariable(
128185500714c460be6452a96be1574d8676d062051cGarrison Venn                             ourTypeInfoNames[exceptionTypesToCatch[i]]));
128285500714c460be6452a96be1574d8676d062051cGarrison Venn  }
128385500714c460be6452a96be1574d8676d062051cGarrison Venn
128485500714c460be6452a96be1574d8676d062051cGarrison Venn  llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0);
12859cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1);
128685500714c460be6452a96be1574d8676d062051cGarrison Venn
12879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // FIXME: Redundant storage which, beyond utilizing value of
12889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  //        caughtResultStore for unwindException storage, may be alleviated
1289d9b0b025612992a0b724eeca8bdf10b1d7a5c355Benjamin Kramer  //        altogether with a block rearrangement
12909cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  builder.CreateStore(caughtResult, caughtResultStorage);
129185500714c460be6452a96be1574d8676d062051cGarrison Venn  builder.CreateStore(unwindException, exceptionStorage);
129285500714c460be6452a96be1574d8676d062051cGarrison Venn  builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
12939f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
12949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // Retrieve exception_class member from thrown exception
1295626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // (_Unwind_Exception instance). This member tells us whether or not
1296626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // the exception is foreign.
12979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::Value *unwindExceptionClass =
1298626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    builder.CreateLoad(builder.CreateStructGEP(
12999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi             builder.CreatePointerCast(unwindException,
1300b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow                                       ourUnwindExceptionType->getPointerTo()),
1301626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                               0));
13029f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1303626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Branch to the externalExceptionBlock if the exception is foreign or
1304626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // to a catch router if not. Either way the finally block will be run.
1305626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass,
13069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                            llvm::ConstantInt::get(builder.getInt64Ty(),
1307626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                   ourBaseExceptionClass)),
1308626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                       exceptionRouteBlock,
1309626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                       externalExceptionBlock);
13109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1311626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // External Exception Block
13129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1313626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(externalExceptionBlock);
13149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
13159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  generateStringPrint(context,
1316626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      module,
13179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                      builder,
1318626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      "Gen: Foreign exception received.\n",
1319626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                      USE_GLOBAL_STR_CONSTS);
13209f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1321626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Branch to the finally block
1322626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateBr(finallyBlock);
13239f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1324626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Exception Route Block
13259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1326626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(exceptionRouteBlock);
13279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
13289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // Casts exception pointer (_Unwind_Exception instance) to parent
1329626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // (OurException instance).
1330626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  //
1331626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Note: ourBaseFromUnwindOffset is usually negative
13329cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::Value *typeInfoThrown = builder.CreatePointerCast(
13339cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                  builder.CreateConstGEP1_64(unwindException,
1334626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                       ourBaseFromUnwindOffset),
13359cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                  ourExceptionType->getPointerTo());
13369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1337626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Retrieve thrown exception type info type
1338626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  //
1339626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Note: Index is not relative to pointer but instead to structure
1340626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  //       unlike a true getelementptr (GEP) instruction
1341626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0);
13429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
13439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::Value *typeInfoThrownType =
1344626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateStructGEP(typeInfoThrown, 0);
13459f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
13469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  generateIntegerPrint(context,
1347626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                       module,
13489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       builder,
13499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       *toPrint32Int,
1350626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                       *(builder.CreateLoad(typeInfoThrownType)),
13519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       "Gen: Exception type <%d> received (stack unwound) "
13529f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       " in " +
13539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       ourId +
1354626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                       ".\n",
1355626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                       USE_GLOBAL_STR_CONSTS);
13569f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1357626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Route to matched type info catch block or run cleanup finally block
13589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex,
13599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                          finallyBlock,
13609cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                          numExceptionsToCatch);
13619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1362626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  unsigned nextTypeToCatch;
13639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1364626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  for (unsigned i = 1; i <= numExceptionsToCatch; ++i) {
1365626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    nextTypeToCatch = i - 1;
1366626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    switchToCatchBlock->addCase(llvm::ConstantInt::get(
1367626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                   llvm::Type::getInt32Ty(context), i),
1368626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                catchBlocks[nextTypeToCatch]);
1369626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
137085500714c460be6452a96be1574d8676d062051cGarrison Venn
1371626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::verifyFunction(*ret);
1372626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  fpm.run(*ret);
13739f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1374626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(ret);
1375626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner}
1376626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner
1377626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner
1378626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner/// Generates function which throws either an exception matched to a runtime
13799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// determined type info type (argument to generated function), or if this
13809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// runtime value matches nativeThrowType, throws a foreign exception by
1381626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner/// calling nativeThrowFunct.
1382626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner/// @param module code for module instance
1383626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner/// @param builder builder instance
13849f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param fpm a function pass manager holding optional IR to IR
1385a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        transformations
1386a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param ourId id used to printing purposes
1387a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param nativeThrowType a runtime argument of this value results in
1388a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        nativeThrowFunct being called to generate/throw exception.
1389a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param nativeThrowFunct function which will throw a foreign exception
1390a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        if the above nativeThrowType matches generated function's arg.
1391a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns generated function
1392a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic
13939f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumillvm::Function *createThrowExceptionFunction(llvm::Module &module,
13949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                             llvm::IRBuilder<> &builder,
139564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                             llvm::FunctionPassManager &fpm,
1396626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                             std::string ourId,
1397626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                             int32_t nativeThrowType,
139864cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                             llvm::Function &nativeThrowFunct) {
139964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::LLVMContext &context = module.getContext();
1400626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  namedValues.clear();
1401626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  ArgTypes unwindArgTypes;
1402c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  unwindArgTypes.push_back(builder.getInt32Ty());
1403626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  ArgNames unwindArgNames;
1404626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  unwindArgNames.push_back("exceptTypeToThrow");
14059f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1406626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::Function *ret = createFunction(module,
1407626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                       builder.getVoidTy(),
1408626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                       unwindArgTypes,
1409626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                       unwindArgNames,
1410626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                       ourId,
1411626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                       llvm::Function::ExternalLinkage,
1412626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                       false,
1413626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                       false);
14149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1415626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Throws either one of our exception or a native C++ exception depending
1416626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // on a runtime argument value containing a type info type.
1417626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
14189f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                          "entry",
1419626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                          ret);
1420626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Throws a foreign exception
14219cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::BasicBlock *nativeThrowBlock = llvm::BasicBlock::Create(context,
14229f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                                "nativeThrow",
14239cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                                ret);
1424626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Throws one of our Exceptions
14259cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::BasicBlock *generatedThrowBlock = llvm::BasicBlock::Create(context,
14269f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                                             "generatedThrow",
14279cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                             ret);
1428626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Retrieved runtime type info type to throw
142964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::Value *exceptionType = namedValues["exceptTypeToThrow"];
14309f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1431626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // nativeThrowBlock block
14329f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1433626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(nativeThrowBlock);
14349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1435626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Throws foreign exception
1436626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateCall(&nativeThrowFunct, exceptionType);
1437626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateUnreachable();
14389f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1439626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // entry block
14409f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1441626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(entryBlock);
14429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1443626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::Function *toPrint32Int = module.getFunction("print32Int");
14449f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  generateIntegerPrint(context,
1445626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                       module,
14469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       builder,
14479f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       *toPrint32Int,
14489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       *exceptionType,
14499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       "\nGen: About to throw exception type <%d> in " +
14509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       ourId +
1451626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                       ".\n",
1452626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                       USE_GLOBAL_STR_CONSTS);
14539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1454626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Switches on runtime type info type value to determine whether or not
14559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // a foreign exception is thrown. Defaults to throwing one of our
1456626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // generated exceptions.
145764cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::SwitchInst *theSwitch = builder.CreateSwitch(exceptionType,
1458626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                     generatedThrowBlock,
1459626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                                     1);
14609f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
14619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context),
1462626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                            nativeThrowType),
1463626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                     nativeThrowBlock);
14649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1465626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // generatedThrow block
14669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1467626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.SetInsertPoint(generatedThrowBlock);
14689f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
14699cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::Function *createOurException = module.getFunction("createOurException");
14709cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::Function *raiseOurException = module.getFunction(
14719cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                        "_Unwind_RaiseException");
14729f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1473626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Creates exception to throw with runtime type info type.
14749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  llvm::Value *exception = builder.CreateCall(createOurException,
14759cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                              namedValues["exceptTypeToThrow"]);
14769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1477626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Throw generated Exception
1478626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateCall(raiseOurException, exception);
1479626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  builder.CreateUnreachable();
14809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1481626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::verifyFunction(*ret);
1482626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  fpm.run(*ret);
14839f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1484626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(ret);
1485a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
1486a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1487a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic void createStandardUtilityFunctions(unsigned numTypeInfos,
14889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                           llvm::Module &module,
148964cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                           llvm::IRBuilder<> &builder);
1490a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
14919f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// Creates test code by generating and organizing these functions into the
1492a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// test case. The test case consists of an outer function setup to invoke
14939f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// an inner function within an environment having multiple catch and single
1494a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// finally blocks. This inner function is also setup to invoke a throw
14959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// function within an evironment similar in nature to the outer function's
1496a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// catch and finally blocks. Each of these two functions catch mutually
1497a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// exclusive subsets (even or odd) of the type info types configured
1498a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// for this this. All generated functions have a runtime argument which
1499a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// holds a type info type to throw that each function takes and passes it
1500a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// to the inner one if such a inner function exists. This type info type is
1501a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// looked at by the generated throw function to see whether or not it should
1502a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// throw a generated exception with the same type info type, or instead call
1503a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// a supplied a function which in turn will throw a foreign exception.
1504a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance
1505a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance
15069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// @param fpm a function pass manager holding optional IR to IR
1507a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        transformations
1508a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param nativeThrowFunctName name of external function which will throw
1509a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        a foreign exception
1510a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @returns outermost generated test function.
15119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumillvm::Function *createUnwindExceptionTest(llvm::Module &module,
15129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                          llvm::IRBuilder<> &builder,
151364cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                          llvm::FunctionPassManager &fpm,
1514a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn                                          std::string nativeThrowFunctName) {
1515626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Number of type infos to generate
1516626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  unsigned numTypeInfos = 6;
15179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1518626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Initialze intrisics and external functions to use along with exception
1519626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // and type info globals.
1520626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  createStandardUtilityFunctions(numTypeInfos,
1521626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                 module,
1522626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                 builder);
15239cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::Function *nativeThrowFunct = module.getFunction(nativeThrowFunctName);
15249f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
15259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  // Create exception throw function using the value ~0 to cause
1526626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // foreign exceptions to be thrown.
15279cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::Function *throwFunct = createThrowExceptionFunction(module,
15289cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                            builder,
15299cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                            fpm,
15309cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                            "throwFunct",
15319cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                            ~0,
15329cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                            *nativeThrowFunct);
1533626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Inner function will catch even type infos
1534626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  unsigned innerExceptionTypesToCatch[] = {6, 2, 4};
15359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
15369cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                    sizeof(unsigned);
15379f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1538626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Generate inner function.
15399cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::Function *innerCatchFunct = createCatchWrappedInvokeFunction(module,
15409cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    builder,
15419cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    fpm,
15429cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    *throwFunct,
15439cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    "innerCatchFunct",
15449cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    numExceptionTypesToCatch,
15459cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    innerExceptionTypesToCatch);
15469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1547626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Outer function will catch odd type infos
1548626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  unsigned outerExceptionTypesToCatch[] = {3, 1, 5};
15499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) /
1550626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  sizeof(unsigned);
15519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1552626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Generate outer function
15539cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn  llvm::Function *outerCatchFunct = createCatchWrappedInvokeFunction(module,
15549cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    builder,
15559cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    fpm,
15569cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    *innerCatchFunct,
15579cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    "outerCatchFunct",
15589cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    numExceptionTypesToCatch,
15599cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                                    outerExceptionTypesToCatch);
15609f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1561626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Return outer function to run
1562626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return(outerCatchFunct);
1563a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
1564a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1565a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1566a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Represents our foreign exceptions
1567a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennclass OurCppRunException : public std::runtime_error {
1568a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennpublic:
1569626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  OurCppRunException(const std::string reason) :
1570626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  std::runtime_error(reason) {}
15719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
157264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  OurCppRunException (const OurCppRunException &toCopy) :
1573626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  std::runtime_error(toCopy) {}
15749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
157564cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  OurCppRunException &operator = (const OurCppRunException &toCopy) {
1576626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    return(reinterpret_cast<OurCppRunException&>(
1577626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                 std::runtime_error::operator=(toCopy)));
1578626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
15799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1580626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  ~OurCppRunException (void) throw () {}
1581a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn};
1582a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1583a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1584a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Throws foreign C++ exception.
1585a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param ignoreIt unused parameter that allows function to match implied
1586a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        generated function contract.
1587a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennextern "C"
1588a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennvoid throwCppException (int32_t ignoreIt) {
1589626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  throw(OurCppRunException("thrown by throwCppException(...)"));
1590a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
1591a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1592a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venntypedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow);
1593a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
15949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// This is a test harness which runs test by executing generated
15957a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner/// function with a type info type to throw. Harness wraps the execution
1596a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// of generated function in a C++ try catch clause.
1597a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param engine execution engine to use for executing generated function.
1598a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        This demo program expects this to be a JIT instance for demo
1599a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        purposes.
1600a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param function generated test function to run
1601a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param typeToThrow type info type of generated exception to throw, or
1602a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        indicator to cause foreign exception to be thrown.
1603a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic
16049f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumivoid runExceptionThrow(llvm::ExecutionEngine *engine,
16059f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                       llvm::Function *function,
1606a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn                       int32_t typeToThrow) {
16079f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1608626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Find test's function pointer
16099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  OurExceptionThrowFunctType functPtr =
1610626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    reinterpret_cast<OurExceptionThrowFunctType>(
1611626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner       reinterpret_cast<intptr_t>(engine->getPointerToFunction(function)));
16129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1613626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  try {
1614626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Run test
1615626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    (*functPtr)(typeToThrow);
1616626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
1617626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  catch (OurCppRunException exc) {
1618626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Catch foreign C++ exception
1619626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr,
1620626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "\nrunExceptionThrow(...):In C++ catch OurCppRunException "
16219f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi            "with reason: %s.\n",
1622626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            exc.what());
1623626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
1624626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  catch (...) {
16259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    // Catch all exceptions including our generated ones. This latter
1626113aa8612010434069fc5b5e09f6b2667e03e173Garrison Venn    // functionality works according to the example in rules 1.6.4 of
1627a6f10317bf2b90a16a931d0f5260cf3920a28d62Dmitri Gribenko    // http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22),
16289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    // given that these will be exceptions foreign to C++
16299f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    // (the _Unwind_Exception::exception_class should be different from
1630113aa8612010434069fc5b5e09f6b2667e03e173Garrison Venn    // the one used by C++).
1631626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr,
1632626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "\nrunExceptionThrow(...):In C++ catch all.\n");
1633626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
1634a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
1635a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1636a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
1637a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// End test functions
1638a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn//
1639a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
16406e6cdd00aaca083779eb70dc238779935da6b9c8Garrison Venntypedef llvm::ArrayRef<llvm::Type*> TypeArray;
1641cad3f77fa8618ac940aa519cd40c403800977273Chris Lattner
16429f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// This initialization routine creates type info globals and
1643a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// adds external function declarations to module.
1644a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param numTypeInfos number of linear type info associated type info types
1645a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn///        to create as GlobalVariable instances, starting with the value 1.
1646a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param module code for module instance
1647a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// @param builder builder instance
1648a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Vennstatic void createStandardUtilityFunctions(unsigned numTypeInfos,
16499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                                           llvm::Module &module,
165064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn                                           llvm::IRBuilder<> &builder) {
16519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
165264cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::LLVMContext &context = module.getContext();
16539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1654626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Exception initializations
16559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1656626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Setup exception catch state
16579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  ourExceptionNotThrownState =
16589cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn    llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
16599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  ourExceptionThrownState =
16609cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn    llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
16619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  ourExceptionCaughtState =
16629cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn    llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
16639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
16649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
16659f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1666626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Create our type info type
16679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  ourTypeInfoType = llvm::StructType::get(context,
16689cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                                          TypeArray(builder.getInt32Ty()));
166985500714c460be6452a96be1574d8676d062051cGarrison Venn
167085500714c460be6452a96be1574d8676d062051cGarrison Venn  llvm::Type *caughtResultFieldTypes[] = {
167185500714c460be6452a96be1574d8676d062051cGarrison Venn    builder.getInt8PtrTy(),
167285500714c460be6452a96be1574d8676d062051cGarrison Venn    builder.getInt32Ty()
167385500714c460be6452a96be1574d8676d062051cGarrison Venn  };
167485500714c460be6452a96be1574d8676d062051cGarrison Venn
167585500714c460be6452a96be1574d8676d062051cGarrison Venn  // Create our landingpad result type
167685500714c460be6452a96be1574d8676d062051cGarrison Venn  ourCaughtResultType = llvm::StructType::get(context,
167785500714c460be6452a96be1574d8676d062051cGarrison Venn                                            TypeArray(caughtResultFieldTypes));
167885500714c460be6452a96be1574d8676d062051cGarrison Venn
1679626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Create OurException type
16809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  ourExceptionType = llvm::StructType::get(context,
1681626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                                           TypeArray(ourTypeInfoType));
16829f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1683626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Create portion of _Unwind_Exception type
1684626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  //
1685626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Note: Declaring only a portion of the _Unwind_Exception struct.
1686626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  //       Does this cause problems?
1687626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  ourUnwindExceptionType =
16889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    llvm::StructType::get(context,
1689c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn                    TypeArray(builder.getInt64Ty()));
16906e6cdd00aaca083779eb70dc238779935da6b9c8Garrison Venn
1691626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  struct OurBaseException_t dummyException;
16929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1693626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Calculate offset of OurException::unwindException member.
16949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
16959cb5086f2a08f691f994e99c244dbc6c1ed5acfaGarrison Venn                            ((uintptr_t) &(dummyException.unwindException));
16969f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1697a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef DEBUG
1698626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  fprintf(stderr,
1699626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          "createStandardUtilityFunctions(...):ourBaseFromUnwindOffset "
1700626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          "= %lld, sizeof(struct OurBaseException_t) - "
1701626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          "sizeof(struct _Unwind_Exception) = %lu.\n",
1702626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          ourBaseFromUnwindOffset,
17039f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi          sizeof(struct OurBaseException_t) -
1704626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner          sizeof(struct _Unwind_Exception));
1705a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif
17069f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1707626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  size_t numChars = sizeof(ourBaseExcpClassChars) / sizeof(char);
17089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1709626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Create our _Unwind_Exception::exception_class value
1710626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  ourBaseExceptionClass = genClass(ourBaseExcpClassChars, numChars);
17119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1712626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Type infos
17139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1714626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  std::string baseStr = "typeInfo", typeInfoName;
1715626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  std::ostringstream typeInfoNameBuilder;
1716626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  std::vector<llvm::Constant*> structVals;
17179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1718626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::Constant *nextStruct;
17199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1720626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Generate each type info
1721626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  //
1722626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Note: First type info is not used.
1723626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  for (unsigned i = 0; i <= numTypeInfos; ++i) {
1724626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    structVals.clear();
1725626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    structVals.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), i));
1726626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    nextStruct = llvm::ConstantStruct::get(ourTypeInfoType, structVals);
17279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1728626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    typeInfoNameBuilder.str("");
1729626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    typeInfoNameBuilder << baseStr << i;
1730626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    typeInfoName = typeInfoNameBuilder.str();
17319f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1732626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Note: Does not seem to work without allocation
17339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    new llvm::GlobalVariable(module,
17349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                             ourTypeInfoType,
17359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                             true,
17369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                             llvm::GlobalValue::ExternalLinkage,
17379f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                             nextStruct,
1738626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                             typeInfoName);
17399f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1740626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    ourTypeInfoNames.push_back(typeInfoName);
1741626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    ourTypeInfoNamesIndex[i] = typeInfoName;
1742626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
17439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1744626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  ArgNames argNames;
1745626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  ArgTypes argTypes;
174664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::Function *funct = NULL;
17479f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1748626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // print32Int
17499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
175077613d4135d5fc8461d0583837b5b850c4a29ecdChris Lattner  llvm::Type *retType = builder.getVoidTy();
17519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1752626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argTypes.clear();
1753c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt32Ty());
1754c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt8PtrTy());
17559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1756626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argNames.clear();
17579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
17589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  createFunction(module,
17599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 retType,
17609f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argTypes,
17619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argNames,
17629f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 "print32Int",
17639f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 llvm::Function::ExternalLinkage,
17649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 true,
1765626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                 false);
17669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1767626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // print64Int
17689f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1769626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  retType = builder.getVoidTy();
17709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1771626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argTypes.clear();
1772c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt64Ty());
1773c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt8PtrTy());
17749f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1775626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argNames.clear();
17769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
17779f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  createFunction(module,
17789f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 retType,
17799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argTypes,
17809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argNames,
17819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 "print64Int",
17829f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 llvm::Function::ExternalLinkage,
17839f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 true,
1784626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                 false);
17859f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1786626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // printStr
17879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1788626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  retType = builder.getVoidTy();
17899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1790626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argTypes.clear();
1791c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt8PtrTy());
17929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1793626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argNames.clear();
17949f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
17959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  createFunction(module,
17969f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 retType,
17979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argTypes,
17989f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argNames,
17999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 "printStr",
18009f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 llvm::Function::ExternalLinkage,
18019f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 true,
1802626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                 false);
18039f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1804626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // throwCppException
18059f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1806626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  retType = builder.getVoidTy();
18079f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1808626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argTypes.clear();
1809c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt32Ty());
18109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1811626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argNames.clear();
18129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
18139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  createFunction(module,
18149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 retType,
18159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argTypes,
18169f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argNames,
18179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 "throwCppException",
18189f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 llvm::Function::ExternalLinkage,
18199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 true,
1820626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                 false);
18219f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1822626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // deleteOurException
18239f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1824626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  retType = builder.getVoidTy();
18259f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1826626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argTypes.clear();
1827c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt8PtrTy());
18289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1829626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argNames.clear();
18309f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
18319f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  createFunction(module,
18329f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 retType,
18339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argTypes,
18349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argNames,
18359f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 "deleteOurException",
18369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 llvm::Function::ExternalLinkage,
18379f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 true,
1838626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                 false);
18399f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1840626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // createOurException
18419f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1842c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  retType = builder.getInt8PtrTy();
18439f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1844626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argTypes.clear();
1845c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt32Ty());
18469f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1847626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argNames.clear();
18489f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
18499f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  createFunction(module,
18509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 retType,
18519f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argTypes,
18529f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argNames,
18539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 "createOurException",
18549f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 llvm::Function::ExternalLinkage,
18559f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 true,
1856626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                 false);
18579f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1858626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // _Unwind_RaiseException
18599f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1860626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  retType = builder.getInt32Ty();
18619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1862626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argTypes.clear();
1863c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt8PtrTy());
18649f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1865626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argNames.clear();
18669f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
18679f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  funct = createFunction(module,
18689f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         retType,
18699f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         argTypes,
18709f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         argNames,
18719f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         "_Unwind_RaiseException",
18729f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         llvm::Function::ExternalLinkage,
18739f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         true,
1874626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                         false);
18759f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
18764c856ee1f8672de5da97d73c05687420eb0049e2NAKAMURA Takumi  funct->setDoesNotReturn();
18779f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1878626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // _Unwind_Resume
18799f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1880626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  retType = builder.getInt32Ty();
18819f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1882626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argTypes.clear();
1883c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt8PtrTy());
18849f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1885626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argNames.clear();
18869f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
18879f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  funct = createFunction(module,
18889f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         retType,
18899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         argTypes,
18909f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         argNames,
18919f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         "_Unwind_Resume",
18929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         llvm::Function::ExternalLinkage,
18939f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                         true,
1894626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                         false);
18959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
18964c856ee1f8672de5da97d73c05687420eb0049e2NAKAMURA Takumi  funct->setDoesNotReturn();
18979f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1898626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // ourPersonality
18999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1900626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  retType = builder.getInt32Ty();
19019f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1902626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argTypes.clear();
1903c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt32Ty());
1904c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt32Ty());
1905c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt64Ty());
1906c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt8PtrTy());
1907c0f33cb59006d42d9d37b02a9158e1a370fc246bGarrison Venn  argTypes.push_back(builder.getInt8PtrTy());
19089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1909626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  argNames.clear();
19109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
19119f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  createFunction(module,
19129f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 retType,
19139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argTypes,
19149f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 argNames,
19159f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 "ourPersonality",
19169f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 llvm::Function::ExternalLinkage,
19179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                 true,
1918626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                 false);
19199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1920626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // llvm.eh.typeid.for intrinsic
19219f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1922626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  getDeclaration(&module, llvm::Intrinsic::eh_typeid_for);
1923a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
1924a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1925a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1926626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner//===----------------------------------------------------------------------===//
1927a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn// Main test driver code.
1928626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner//===----------------------------------------------------------------------===//
1929a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn
1930a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// Demo main routine which takes the type info types to throw. A test will
19319f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi/// be run for each given type info type. While type info types with the value
1932a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// of -1 will trigger a foreign C++ exception to be thrown; type info types
1933a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// <= 6 and >= 1 will be caught by test functions; and type info types > 6
1934a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// will result in exceptions which pass through to the test harness. All other
1935a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn/// type info types are not supported and could cause a crash.
193664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Vennint main(int argc, char *argv[]) {
1937626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  if (argc == 1) {
1938626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr,
1939626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "\nUsage: ExceptionDemo <exception type to throw> "
1940626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "[<type 2>...<type n>].\n"
1941626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "   Each type must have the value of 1 - 6 for "
1942626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "generated exceptions to be caught;\n"
1943626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "   the value -1 for foreign C++ exceptions to be "
1944626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "generated and thrown;\n"
1945626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "   or the values > 6 for exceptions to be ignored.\n"
1946626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "\nTry: ExceptionDemo 2 3 7 -1\n"
1947626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner            "   for a full test.\n\n");
1948626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    return(0);
1949626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  }
19509f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1951626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // If not set, exception handling will not be turned on
1952d40e103ea5bca8a223fc8261b3322b9454e9af12Peter Collingbourne  llvm::TargetOptions Opts;
19539f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1954626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::InitializeNativeTarget();
1955c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola  llvm::InitializeNativeTargetAsmPrinter();
195664cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::LLVMContext &context = llvm::getGlobalContext();
1957626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::IRBuilder<> theBuilder(context);
19589f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1959626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Make the module, which holds all the code.
196064cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::Module *module = new llvm::Module("my cool jit", context);
19619f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
19623c2b0e171f02f2bd0c2506101a1d6e66d7e9bdeeNAKAMURA Takumi  llvm::RTDyldMemoryManager *MemMgr = new llvm::SectionMemoryManager();
1963c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola
1964626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  // Build engine with JIT
1965626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  llvm::EngineBuilder factory(module);
1966626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  factory.setEngineKind(llvm::EngineKind::JIT);
1967626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  factory.setAllocateGVsWithCode(false);
1968d40e103ea5bca8a223fc8261b3322b9454e9af12Peter Collingbourne  factory.setTargetOptions(Opts);
19693c2b0e171f02f2bd0c2506101a1d6e66d7e9bdeeNAKAMURA Takumi  factory.setMCJITMemoryManager(MemMgr);
1970c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola  factory.setUseMCJIT(true);
197164cfcefdeb05bd955659dfe07435c9ca6ae8efacGarrison Venn  llvm::ExecutionEngine *executionEngine = factory.create();
19729f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1973626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  {
1974626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    llvm::FunctionPassManager fpm(module);
19759f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
19769f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    // Set up the optimizer pipeline.
1977626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Start with registering info about how the
1978626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // target lays out data structures.
19792b4b44e0d2e95fc695eafcc4d192fe1ae261e01eMicah Villmow    fpm.add(new llvm::DataLayout(*executionEngine->getDataLayout()));
19809f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1981626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Optimizations turned on
1982a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#ifdef ADD_OPT_PASSES
19839f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1984626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Basic AliasAnslysis support for GVN.
1985626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fpm.add(llvm::createBasicAliasAnalysisPass());
19869f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1987626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Promote allocas to registers.
1988626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fpm.add(llvm::createPromoteMemoryToRegisterPass());
19899f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1990626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Do simple "peephole" optimizations and bit-twiddling optzns.
1991626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fpm.add(llvm::createInstructionCombiningPass());
19929f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1993626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Reassociate expressions.
1994626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fpm.add(llvm::createReassociatePass());
19959f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
1996626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Eliminate Common SubExpressions.
1997626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fpm.add(llvm::createGVNPass());
19989f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
19999f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    // Simplify the control flow graph (deleting unreachable
2000626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // blocks, etc).
2001626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fpm.add(llvm::createCFGSimplificationPass());
2002a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn#endif  // ADD_OPT_PASSES
20039f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
2004626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fpm.doInitialization();
20059f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
2006626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // Generate test code using function throwCppException(...) as
2007626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    // the function which throws foreign exceptions.
20089f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    llvm::Function *toRun =
20099f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi    createUnwindExceptionTest(*module,
20109f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                              theBuilder,
201185500714c460be6452a96be1574d8676d062051cGarrison Venn                              fpm,
201285500714c460be6452a96be1574d8676d062051cGarrison Venn                              "throwCppException");
20139f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
2014c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola    executionEngine->finalizeObject();
2015c8b9551a8fe52cefbefeac820c81996281fff4e5Rafael Espindola
2016626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, "\nBegin module dump:\n\n");
20179f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
2018626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    module->dump();
20199f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
2020626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, "\nEnd module dump:\n");
20219f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
2022626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, "\n\nBegin Test:\n");
20239f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
2024626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    for (int i = 1; i < argc; ++i) {
2025626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      // Run test for each argument whose value is the exception
2026626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner      // type to throw.
20279f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi      runExceptionThrow(executionEngine,
20289f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi                        toRun,
2029626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner                        (unsigned) strtoul(argv[i], NULL, 10));
2030626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    }
20319f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
2032626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner    fprintf(stderr, "\nEnd Test:\n\n");
20339f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi  }
20349f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
2035626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  delete executionEngine;
20369f469a0ca36a6b07c863bffa52357f3db3afcec8NAKAMURA Takumi
2037626ab1ccad703deefd386fc732d875f8e1319edbChris Lattner  return 0;
2038a2c2f1ae849c8091ca8eabfb21eea7947c180c18Garrison Venn}
2039